1.定义
- Redis集群是Redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能。
- 3.0版本之前的redis是不支持集群的,Redis3.0之后支持集群。
- 一个Redis集群通常由多个节点组成,通过握手(cluster meet命令)添加节点
2.槽指派
- Redis集群通过分片的方式保存数据库中的键值对,集群中的整个数据库被分为16384个槽(slot),每个节点可以处理0-16384个槽
- 当数据库中的16384个槽都有节点在处理时,集群就处于上线状态
- 命令cluster addslots < slot>可以将一个或多个槽指派给节点负责
- slot属性是一个二进制数组,若slots[i]=1,表示节点负责处理槽i,若slots[i]=0,则表示节点不负责处理槽i
3.在集群中执行命令
- 判断客户端是否需要转向的流程
- 节点保存键值的步骤
- 计算键属于哪个槽
- 判断槽是否由当前节点负责处理
- moved错误(该错误被隐藏,但在单机模式下会打印错误)
- 节点数据库的实现(只能使用0号库)
4.重新分片
- 将任意数量已经指派给某个节点(源节点)的槽改为指派给另一个节点(目标节点),并且相关槽所属的键值对也会从源节点被移动到目标节点。可在线操作。
- 对slot进行重新分片的过程
- ASK错误:在节点迁移的过程中,被迁移槽的一部分键值对保存在源节点,而另一部分保存在目的节点。
- 判断是否发送ASK错误的过程
5.消息
- meet消息:表示接收到服务器发送的cluster meet命令
- ping消息:对五个节点中最长时间没有发送过ping消息的节点发送ping消息,以检测是否在线
- pong消息:接收到meet或ping消息
- fail消息:当A节点判断B节点进入fail状态,A节点就会向集群广播一条关于节点B的fail消息
- publish消息:当节点接收到publish命令时,向集群广播一条publish消息
注:消息由消息头和消息正文组成。
6.集群的配置(至少三个master)
- 创建一个文件夹redis-cluster,分别创建6个文件夹:7001到7006
- 把redis.conf文件分别拷贝到6个文件夹中
- 修改redis.conf文件,设置后台启动:daemonize yes ;设置端口号:port 700*、绑定当前机器的ip: bind 192.168.254.142;
- 指定数据文件存放位置 : 将dir /usr/ocal/redis/etc更改为dir /usr/ocal/redis-cluster/700*
- 启动集群模式 :Cluster-enabled yes
- 更改每个节点的配置文件(每个节点相互联系):Cluster-config-file nodes-700*.conf
- 设置集群的失效时间:Cluster-node-timeout 15000
- 开启AOF持久化模式:Appendonly yes
- 安装软件包 ruby 、 rubygems 、gem install redis(安装redis和ruby的接口)
- 分别启动6个redis实例,检查是否成功。
7.集群的优点
- 容错性
解决在单服redis的单点问题。在一个或多个节点出现宕机的情况下,集群内部通过投票的机制能够快速的进行选举和不停机的情况下进行服务持续提供。 - 扩展性
相比单服在升级性能过程中,集群也能够很好的实现缓存的性能升级,如多节点的热部署。 - 性能提升
解决单个服务器的内存瓶颈,性能的在扩展过程中,也能够随之的体现出来。
8.集群的问题及解决方案
8.1 节点宕机恢复间
- 出现的问题:任何一个节点从宕机到被标记为 FAIL 摘除,一般需要经过 30 秒,主库的摘除可能会影响数据的完整性。
- 解决方案: 使用ZooKeeper监控redis节点,并做高可用。具体原理如下图所示:
8.2 异地同步数据
- 出现的问题:跨地域网络不稳定,带宽有限且昂贵。
- 解决方案:增加一个同步集群,用来同步异地间的数据。流程图如下
8.3 持久化慢
- 出现的问题:生成 RDB 的过程会调用 Fork 产生一个子进程去写数据到硬盘,内存用量达到 10 G 及以上时,会造成秒级的阻塞。
- 解决方案:异步线程负责把变更刷到硬盘的 Backlog,且写 AOF 是完全异步。流程图如下
8.4 热点key
- 出现的问题:热点key可能造成缓存击穿
- 解决方案:对热点key进行流控,将热点key迁移到供访问热点key的热点slot中。
参考
- 《Redis设计与实现(第二版)》—黄健宏
- 美团万亿级 KV 存储架构与实践
- 全面剖析Redis Cluster原理和应用