教你在 Kubernetes 上部署 Redis 高可用集群?

简介: 教你在 Kubernetes 上部署 Redis 高可用集群?

Redis 介绍

Redis 代表REmote DIctionary Server是一种开源的内存中数据存储,通常用作数据库,缓存或消息代理。它可以存储和操作高级数据类型,例如列表,地图,集合和排序集合。由于Redis接受多种格式的密钥,因此可以在服务器上执行操作,从而减少了客户端的工作量。它仅将磁盘用于持久性,而将数据库完全保存在内存中。Redis是一种流行的数据存储解决方案,并被GitHubPinterestSnapchatTwitterStackOverflowFlickr等技术巨头所使用。

为什么使用 Redis

  • 它的速度非常快。它是用 ANSI C 编写的,并且可以在 POSIX 系统上运行,例如 Linux,Mac OS X 和 Solaris。
  • Redis 通常被排名为最流行的键/值数据库和最流行的与容器一起使用的 NoSQL 数据库。
  • 其缓存解决方案减少了对云数据库后端的调用次数。
  • 应用程序可以通过其客户端 API 库对其进行访问。
  • 所有流行的编程语言都支持 Redis。
  • 它是开源且稳定的。

什么是 Redis 集群

Redis Cluster 是一组 Redis 实例,旨在通过对数据库进行分区来扩展数据库,从而使其更具弹性。群集中的每个成员(无论是主副本还是辅助副本)都管理哈希槽的子集。如果主机无法访问,则其从机将升级为主机。在由三个主节点组成的最小 Redis 群集中,每个主节点都有一个从节点(以实现最小的故障转移),每个主节点都分配有一个介于 0 到 16,383 之间的哈希槽范围。节点 A 包含从 0 到 5000 的哈希槽,节点 B 从 5001 到 10000,节点 C 从 10001 到 16383。群集内部的通信是通过内部总线进行的,使用协议传播有关群集的信息或发现新节点。

在 Kubernetes 中部署 Redis 集群

Kubernetes中部署Redis集群面临挑战,因为每个 Redis 实例都依赖于一个配置文件,该文件可以跟踪其他集群实例及其角色。为此,我们需要结合使用Kubernetes StatefulSetsPersistentVolumes

克隆部署文件

git clone https://github.com/llmgo/redis-sts.git

创建 statefulset 类型资源

[root@node01 redis-sts]# cat redis-sts.yml 
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
data:
  update-node.sh: |
    #!/bin/sh
    REDIS_NODES="/data/nodes.conf"
    sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES}
    exec "$@"
  redis.conf: |+
    cluster-enabled yes
    cluster-require-full-coverage no
    cluster-node-timeout 15000
    cluster-config-file /data/nodes.conf
    cluster-migration-barrier 1
    appendonly yes
    protected-mode no
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
spec:
  serviceName: redis-cluster
  replicas: 6
  selector:
    matchLabels:
      app: redis-cluster
  template:
    metadata:
      labels:
        app: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:5.0.5-alpine
        ports:
        - containerPort: 6379
          name: client
        - containerPort: 16379
          name: gossip
        command: ["/conf/update-node.sh", "redis-server", "/conf/redis.conf"]
        env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        volumeMounts:
        - name: conf
          mountPath: /conf
          readOnly: false
        - name: data
          mountPath: /data
          readOnly: false
      volumes:
      - name: conf
        configMap:
          name: redis-cluster
          defaultMode: 0755
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi
      storageClassName: standard
$ kubectl apply -f redis-sts.yml
configmap/redis-cluster created
statefulset.apps/redis-cluster created
$ kubectl get pods -l app=redis-cluster
NAME              READY   STATUS    RESTARTS   AGE
redis-cluster-0   1/1     Running   0          53s
redis-cluster-1   1/1     Running   0          49s
redis-cluster-2   1/1     Running   0          46s
redis-cluster-3   1/1     Running   0          42s
redis-cluster-4   1/1     Running   0          38s
redis-cluster-5   1/1     Running   0          34s

创建 service

[root@node01 redis-sts]# cat redis-svc.yml   
---  
apiVersion: v1  
kind: Service  
metadata:  
  name: redis-cluster  
spec:  
  type: ClusterIP  
  clusterIP: 10.96.0.100  
  ports:  
  - port: 6379  
    targetPort: 6379  
    name: client  
  - port: 16379  
    targetPort: 16379  
    name: gossip  
  selector:  
    app: redis-cluster  
$ kubectl apply -f redis-svc.yml  
service/redis-cluster created  
$ kubectl get svc redis-cluster  
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)              AGE  
redis-cluster   ClusterIP   10.96.0.100   <none>        6379/TCP,16379/TCP   35s

初始化 redis cluster

下一步是形成Redis集群。为此,我们运行以下命令并键入yes以接受配置。前三个节点成为主节点,后三个节点成为从节点。

$ kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 ')  
>>> Performing hash slots allocation on 6 nodes...  
Master[0] -> Slots 0 - 5460  
Master[1] -> Slots 5461 - 10922  
Master[2] -> Slots 10923 - 16383  
Adding replica 10.244.2.11:6379 to 10.244.9.19:6379  
Adding replica 10.244.9.20:6379 to 10.244.6.10:6379  
Adding replica 10.244.8.15:6379 to 10.244.7.8:6379  
M: 00721c43db194c8f2cacbafd01fd2be6a2fede28 10.244.9.19:6379  
   slots:[0-5460] (5461 slots) master  
M: 9c36053912dec8cb20a599bda202a654f241484f 10.244.6.10:6379  
   slots:[5461-10922] (5462 slots) master  
M: 2850f24ea6367de58fb50e632fc56fe4ba5ef016 10.244.7.8:6379  
   slots:[10923-16383] (5461 slots) master  
S: 554a58762e3dce23ca5a75886d0ccebd2d582502 10.244.8.15:6379  
   replicates 2850f24ea6367de58fb50e632fc56fe4ba5ef016  
S: 20028fd0b79045489824eda71fac9898f17af896 10.244.2.11:6379  
   replicates 00721c43db194c8f2cacbafd01fd2be6a2fede28  
S: 87e8987e314e4e5d4736e5818651abc1ed6ddcd9 10.244.9.20:6379  
   replicates 9c36053912dec8cb20a599bda202a654f241484f  
Can I set the above configuration? (type 'yes' to accept): yes  
>>> Nodes configuration updated  
>>> Assign a different config epoch to each node  
>>> Sending CLUSTER MEET messages to join the cluster  
Waiting for the cluster to join  
...  
>>> Performing Cluster Check (using node 10.244.9.19:6379)  
M: 00721c43db194c8f2cacbafd01fd2be6a2fede28 10.244.9.19:6379  
   slots:[0-5460] (5461 slots) master  
   1 additional replica(s)  
M: 9c36053912dec8cb20a599bda202a654f241484f 10.244.6.10:6379  
   slots:[5461-10922] (5462 slots) master  
   1 additional replica(s)  
S: 87e8987e314e4e5d4736e5818651abc1ed6ddcd9 10.244.9.20:6379  
   slots: (0 slots) slave  
   replicates 9c36053912dec8cb20a599bda202a654f241484f  
S: 554a58762e3dce23ca5a75886d0ccebd2d582502 10.244.8.15:6379  
   slots: (0 slots) slave  
   replicates 2850f24ea6367de58fb50e632fc56fe4ba5ef016  
S: 20028fd0b79045489824eda71fac9898f17af896 10.244.2.11:6379  
   slots: (0 slots) slave  
   replicates 00721c43db194c8f2cacbafd01fd2be6a2fede28  
M: 2850f24ea6367de58fb50e632fc56fe4ba5ef016 10.244.7.8:6379  
   slots:[10923-16383] (5461 slots) master  
   1 additional replica(s)  
[OK] All nodes agree about slots configuration.  
>>> Check for open slots...  
>>> Check slots coverage...  
[OK] All 16384 slots covered.

验证集群

[root@node01 redis-sts]# kubectl exec -it redis-cluster-0 -- redis-cli cluster info  
cluster_state:ok  
cluster_slots_assigned:16384  
cluster_slots_ok:16384  
cluster_slots_pfail:0  
cluster_slots_fail:0  
cluster_known_nodes:6  
cluster_size:3  
cluster_current_epoch:6  
cluster_my_epoch:1  
cluster_stats_messages_ping_sent:16  
cluster_stats_messages_pong_sent:22  
cluster_stats_messages_sent:38  
cluster_stats_messages_ping_received:17  
cluster_stats_messages_pong_received:16  
cluster_stats_messages_meet_received:5  
cluster_stats_messages_received:38  
[root@node01 redis-sts]# for x in $(seq 0 5); do echo "redis-cluster-$x"; kubectl exec redis-cluster-$x -- redis-cli role; echo; done  
redis-cluster-0  
master  
14  
10.244.2.11  
6379  
14  
redis-cluster-1  
master  
28  
10.244.9.20  
6379  
28  
redis-cluster-2  
master  
28  
10.244.8.15  
6379  
28  
redis-cluster-3  
slave  
10.244.7.8  
6379  
connected  
28  
redis-cluster-4  
slave  
10.244.9.19  
6379  
connected  
14  
redis-cluster-5  
slave  
10.244.6.10  
6379  
connected  
28

测试集群

我们想使用集群,然后模拟节点的故障。对于前一项任务,我们将部署一个简单的 Python 应用程序,而对于后者,我们将删除一个节点并观察集群行为。

部署点击计数器应用

我们将一个简单的应用程序部署到集群中,并在其前面放置一个负载平衡器。此应用程序的目的是在将计数器值作为 HTTP 响应返回之前,增加计数器并将其存储在 Redis 集群中。

$ kubectl apply -f app-deployment-service.yml  
service/hit-counter-lb created  
deployment.apps/hit-counter-app created

在此过程中,如果我们继续加载页面,计数器将继续增加,并且在删除Pod之后,我们看到没有数据丢失。

$  curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 20 times since deployment.  
$  curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 21 times since deployment.  
$ curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 22 times since deployment.  
$ kubectl delete pods redis-cluster-0  
pod "redis-cluster-0" deleted  
$ kubectl delete pods redis-cluster-1  
pod "redis-cluster-1" deleted  
$  curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 23 times since deployment.

参考文档

  1. [redis-cluster集群配置1] http://llmgo.cn/post/redis-003/
  2. [redis-cluster集群配置2] http://www.yunweipai.com/36338.html

结语

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
2月前
|
存储 NoSQL Redis
手把手教你用 Docker 部署 Redis
Redis是高性能内存数据库,支持多种数据结构,适用于缓存、消息队列等场景。本文介绍如何通过Docker快速拉取轩辕镜像并部署Redis,涵盖快速启动、持久化存储及docker-compose配置,助力开发者高效搭建稳定服务。
904 8
|
3月前
|
存储 监控 NoSQL
Redis高可用架构全解析:从主从复制到集群方案
Redis高可用确保服务持续稳定,避免单点故障导致数据丢失或业务中断。通过主从复制实现数据冗余,哨兵模式支持自动故障转移,Cluster集群则提供分布式数据分片与水平扩展,三者层层递进,保障读写分离、容灾切换与大规模数据存储,构建高性能、高可靠的Redis架构体系。
|
10月前
|
存储 NoSQL Redis
Docker 部署 Redis
在使用 Docker 部署 Redis 时,为实现数据持久化,需正确挂载容器内的数据目录到宿主机。推荐命令如下: ``` docker run -d --name redis -v /mnt/data/redis:/data -p 6379:6379 redis ``` 该命令将宿主机的 `/mnt/data/redis` 目录挂载到容器的 `/data` 目录,确保 Redis 数据持久化。此路径更通用,适合大多数场景。避免使用不匹配的挂载路径,如 `/var/lib/redis` 或 `/mnt/data/redis` 到非默认目录,以防止数据无法正确持久化。
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
802 26
|
11月前
|
存储 负载均衡 NoSQL
搭建高可用及负载均衡的Redis
通过本文介绍的高可用及负载均衡Redis架构,可以有效提升Redis服务的可靠性和性能。主从复制、哨兵模式、Redis集群以及负载均衡技术的结合,使得Redis系统在应对高并发和数据一致性方面表现出色。这些配置和技术不仅适用于小型应用,也能够支持大规模企业级应用的需求。希望本文能够为您的Redis部署提供实用指导和参考。
831 9
|
监控 NoSQL 网络协议
【Azure Redis】部署在AKS中的应用,连接Redis高频率出现timeout问题
查看Redis状态,没有任何异常,服务没有更新,Service Load, CPU, Memory, Connect等指标均正常。在排除Redis端问题后,转向了AKS中。 开始调查AKS的网络状态。最终发现每次Redis客户端出现超时问题时,几乎都对应了AKS NAT Gateway的更新事件,而Redis服务端没有任何异常。因此,超时问题很可能是由于NAT Gateway更新事件导致TCP连接被重置。
256 7
|
存储 NoSQL 大数据
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
180 3
|
存储 监控 NoSQL
Redis 部署选型方案
Redis 部署选型方案 ==前言== 项目即将使用Redis,本文对Redis的部署方案,进行选型分析。 ==一、部署方案介绍== ==1)、单机版== 1-单机版.
1788 0
|
7月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
2月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。