一 Redis cluster搭建背景
-
通过哈希一致性搭建节点容易造成数据倾斜,key值强耦合
-
搭建主从复制,可以读写分离,备份主节点数据,但主节点宕机产生单点故障问题
-
搭建哨兵集群可以监控主服务状态,投票选择主节点,实现高可用
-
Redis cluster沿用了哨兵集群逻辑,引入Hash槽
1.哈希槽节点结构
-
16384位的二进制(2048个元素的byte数组)
在节点创建初始化状态,二进制的所有位的值时0表示false,一旦分配了槽道将会根据槽道的管理状态指定不同为的二进制值为1/0;对于二进制分配下标计算(位移计算获取的)0-16383,和槽道对应;利用二进制得到对应关系,槽道号和二进制的位的值1/0对应关系,如果槽道号对应的二进制时1,表示当前节点管理这个槽道,如果是0表示不管理。(16384位对应16384个哈希槽)
-
16384个元素的数组(引用对象)
搭建好集群后,赋值完槽道后,所有节点维护了一个完全相同的内存数组,这个数组16384个元素,下标[0-16383],每一个下标对应的元素内容,是一个指向槽道号管理节点的内存对象的记录;
2.Redis slots:
(1)一共有16384个槽,每台服务器分管其中的一部分<br> (2)插入一个数据的时候,先根据CRC16算法计算key对应的值,然后用该值对16384取余数(即CRC16(key) mod 16384),确定将数据放到哪个槽里面<br> (3)在增加的时候,之前的节点各自分出一些槽给新节点,对应的数据也一起迁出<br> (4)客户端可以向任何一个Redis节点发送请求,然后由节点将请求重定向到正确的节点上<br>
-
二 Redis cluster配置
- 注释掉bind,设置protected-mode为no,使redis可以远程访问
- daemonize设置为yes(以守护进程运行)
- 设置dbfilename(dump.rdb 持久化方式),logfile
- appendonly 设置为yes 并配置appendfilename
- cluster-enable 设置为yes 并设置一个cluster-config-file
- requirepass 设置密码
对比 | rdb | aof |
---|---|---|
运行模式 | 记录的数据是key-value | 记录的整个执行的命令 set key value |
文件大小 | 比较小 | 比较大 |
redis-server加载顺序 | 需要单独开启 | aof优先级大于rdb |
优缺点 | 缺点:会在宕机时造成数据的丢失更多 优点:批量操作,效率更高,小数据量时使用rdb效率比aop高 2倍以上的效率 | 优点:数据同步时间接近实时;数据备份可靠性高,丢失数据少 缺点:同步的实时性,增加redis-server的压力 |
使用场景 | 需要一定的数据恢复能力,不要求数据可靠性极强(数据恢复时,越全可靠性越高);数据量不大的情况可以选择rdb | 对数据的可靠性要求极高,可以使用aof,在aof模式下,最多丢失2秒的数据 |
三 搭建集群
- 启动redis-server: redis-server redis-cluster.conf …
- 连接redis-cli: redis-cli -c -h xxx -p xxx -a xxx [-c 连接集群 -h 主机 -p 端口 -a 密码]
- 查看集群信息: info replication/cluster nodes/cluster info查看相应信息
- 集群创建(redis 5版本): redis-cli --cluster create
- (redis 5之前 需要在redis-trib.rb create ip:port…)
./redis-cli --cluster create ip:port ip:port ip:port ip:port ip:port --cluster-replicas 1
- [–cluster-replicas 1] 代表 1:1复制
注:redis集群总线端口为redis客户端端口加上10000,比如说你的redis 6379端口为客户端通讯端口,那么16379端口为集群总线端口,不打开对应通讯端口会卡在Waiting for the cluster to join …
- 新增节点: (redis 5版本) redis-cli --cluster add-node new_host:new_port existing_host:existing_port
- redis 5之前 需要在 redis-trib.rb add-node add-node
- 新增节点salve: redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id master-id
- 若不加master-id为随机称为某个master的salve
- redis 5之前 redis-trib.rb add-node --slave --master-id master-id new_host:new_port existing_host:existing_port)
- 删除节点: redis-cli --cluster del-node host:port node-id
- redis 5之前 redis-trib.rb del-node host:port node-id
- 如果待删除的是master节点,则在删除之前需要将该master负责的slots先全部迁到其它master。
- 如果删除后,其它节点还看得到这个被删除的节点,则可通过FORGET命令解决 CLUSTER FORGET node-id
- 变更主从关系: (登陆进redis)cluster replicate master-node-id
- 变更主节点时必须为空且未分配slots
- 迁移slots: (登陆进redis)
- eg:将值为8的slot从源节点A迁移到目标节点B
- 在目标节点B上执行:CLUSTER SETSLOT 8 IMPORTING src-A-node-id
- 在源节点A上执行:CLUSTER SETSLOT 8 MIGRATING dst-B-node-id
- redis 5之前 redis-trib.rb reshard host:port(有slots的node)
- 人工主备切换: (在slave客户端中)CLUSTER FAILOVER