Redis集群

Redis 集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N即切片集群,也叫分片集群。解决了大型单实例持久化阻塞主线程的问题,也方便了扩容问题。

并且Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。

image-20230419144924701

数据切片和实例的对应分布关系

切片集群是一种保存大量数据的通用机制,这个机制可以有不同的实现方案。一般使用的是Redis Cluster,这里也讲的是Redis Cluster。

Redis Cluster 方案采用哈希槽(Hash Slot,接下来我会直接称之为 Slot),来处理数据和实例之间的映射关系。

在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中。

映射过程:

  • 根据键值对的 key,按照CRC16 算法计算一个 16 bit 的值
  • 再用这个 16bit 值对 16384 取模,得到的模数代表一个相应编号的哈希槽。

哈希槽分摊:

  • 可以使用cluster create命令创建集群,自动平均分配
  • 也可以使用cluster meet命令手动建立实例间的连接,形成集群,再使用 cluster addslots 命令,指定每个实例上的哈希槽个数。(在手动分配哈希槽时,需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作。)

集群的方案选择

集群方案目前主要有两种:

  • Codis
  • Redis Cluster

两者区别:

image-20230405143841170

选择建议:

  1. 从稳定性和成熟度来看,Codis 应用得比较早,在业界已经有了成熟的生产部署。虽然 Codis 引入了 proxy 和 Zookeeper,增加了集群复杂度,但是,proxy 的无状态设计和 Zookeeper 自身的稳定性,也给 Codis 的稳定使用提供了保证。而 Redis Cluster 的推出时间晚于 Codis,相对来说,成熟度要弱于 Codis,如果你想选择一个成熟稳定的方案,Codis 更加合适些。
  2. 从业务应用客户端兼容性来看,连接单实例的客户端可以直接连接 codis proxy,而原本连接单实例的客户端要想连接 Redis Cluster 的话,就需要开发新功能。所以,如果你的业务应用中大量使用了单实例的客户端,而现在想应用切片集群的话,建议你选择 Codis,这样可以避免修改业务应用中的客户端。
  3. 从使用 Redis 新命令和新特性来看,Codis server 是基于开源的 Redis 3.2.8 开发的,所以,Codis 并不支持 Redis 后续的开源版本中的新增命令和数据类型。另外,Codis 并没有实现开源 Redis 版本的所有命令,比如 BITOP、BLPOP、BRPOP,以及和与事务相关的 MUTLI、EXEC 等命令。Codis 官网上列出了不被支持的命令列表,你在使用时记得去核查一下。所以,如果你想使用开源 Redis 版本的新特性,Redis Cluster 是一个合适的选择。
  4. 从数据迁移性能维度来看,Codis 能支持异步迁移,异步迁移对集群处理正常请求的性能影响要比使用同步迁移的小。所以,如果你在应用集群时,数据迁移比较频繁的话,Codis 是个更合适的选择。

客户端如何定位数据?

在定位键值对数据时,它所处的哈希槽是可以通过计算得到的,但是还需要指定哈希槽分布在哪个实例上。

  • Redis 实例会把自己的哈希槽信息发给和它相连接的其它实例,来完成哈希槽分配信息的扩散。当实例之间相互连接后,每个实例就有所有哈希槽的映射关系了。

  • 客户端收到哈希槽信息后,会把哈希槽信息缓存在本地。当客户端请求键值对时,会先计算键所对应的哈希槽,然后就可以给相应的实例发送请求了。

    当对应关系已经发生变化:

    Redis Cluster 方案提供了一种重定向机制,如果实例上没有该数据,会用MOVED命令带着新实例地址响应给客户端,收到后更新本地缓存再重新请求

    当Slot正在进行迁移:

    如果实例上没有该数据,会用ASK命令来返回新实例地址,收到后不会更新本地缓存,并发送ASKING命令再发送操作命令。

无中心化集群的搭建

  1. 进行每个服务器的配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    include /home/bigdata/redis.conf  #导入基础配置文件
    port 6379 #设置端口
    pidfile "/var/run/redis_6379.pid" #设置redis的进程文件
    dbfilename "dump6379.rdb" #设置数据备份文件
    dir "/home/bigdata/redis_cluster" #设置数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录
    logfile "/home/bigdata/redis_cluster/redis_err_6379.log" #设置日志文件地址
    cluster-enabled yes #打开集群模式
    cluster-config-file nodes-6379.conf #设定节点配置文件名不需要我们创建,由redis自己维护

    cluster-node-timeout 15000 #设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换。
  2. 启动各个redis服务

  3. 合成集群:redis-cli --cluster create --cluster-replicas 1 所有主机ip:端口(每一台主机后跟几个从机,这里写1是一主一从 –replicas 1 采用最简单的方式配置集群,一台主机,一台从机;一般前几个是主后几个是从)

  4. 以集群方式连接:redis-cli -c -p 6379 -a 123321

  5. 进入客户端后可以通过cluster nodes命令查看集群状态

查询集群中某个插槽的值:CLUSTER GETKEYSINSLOT <slot> <count>