Skip to content

redis集群分片

cluster

  • 自带sentinel故障转移机制,内置高可用支持
  • 客户端连接一个可用节点
  • solt 分配到对应节点

solt (16384)

最大节点为16384 建议不要超过1000

latex
2^{14}=16384

CRC16算法

槽位缩容和扩容 比如集群添加主节点 或者 主节点下线

槽位映射

哈希取余分区

宕机会发生数据混乱

一致性哈希算法

解决分布式缓存数据变动的问题 构建一致性哈希环 ip节点映射 落到服务器上 容错性 扩展性

哈希槽分区

解决均匀分配问题 为什么是2^{14} 而不是2^{16} 心跳包

2^{16} 的心跳包是8k 2^{16}/8=8k

集群节点不要超过1000 槽位越小 节点越少

集群不保证强一致性

搭建

三主三从 启动六台redis实例

配置x6

text
daemonize yes
bind 0.0.0.0
protected-mode no
port 6379
dir ./
pidfile "./redis.pid"
logfile "./redis.log"
dbfilename dump.rdb
appendonly yes
appendfilename appendonly.aof
requirepass 123456
masterauth 123456

cluster-enabled yes
cluster-config-file cluster.conf
cluster-node-timeout 5000

构建主从关系

bash
redis-cli -a 123456 --cluster create --cluster-replicas 1 \
ip:port [ip:port...]

yes

构建集群 img.png

链接客户端操作

链接客户端操作 cluster_connect_no_cluster.png

bash
redis-cli -a 123456 -c

异常

主节点宕机 从节点上位成为主节点 节点恢复成为从节点入队

节点从属调整

主从切换

bash
CLUSTER FAILOVER

主从扩容关系

添加2个节点

node1 node2

通过现有节点加入集群

bash
redis-cli  -a 123456 --cluster add-node \
<new-node-ip:port> <existing-node-ip:port>

检查状态

bash
redis-cli -a 123456 --cluster check <existing-node-ip:port>

cluster_add_new_node.png 重新hash

bash
redis-cli --cluster reshard <existing-node-ip:port>

重新分配槽点slot cluster_rehash.png

给新添加的节点添加从节点

bash
redis-cli -a 111111 --cluster add-node <new-slave-ip:port> <master-ip:port> \
--cluster-slave --cluster-master-id <id>

集群缩容

注意仅能删除从节点或者没有槽位的master节点 先将槽位分给别人 cluster_node_del_rehash.png

bash
redis-cli --cluster del-node <existing-node-ip:port> id

注意 不在一个槽位下无法直接使用mset mget

cluster_mget.png 使用统配

bash
meget k1{z} v1 k2{z} v2

cluster_mset{}.png

docker启动redis集群3主三从

配置文件

docker-compose.yml

yaml
name: "redis-cluster"
services:
  redis1:
    image: registry.cn-beijing.aliyuncs.com/zbzly/redis
    ports:
      - "6381:6381"
      - "16381:16381"
    env_file:
      - .env
    command:
      - redis-server
      - --port 6381
      - --cluster-announce-port 6381
      - --cluster-announce-bus-port 16381
      - --bind ${bind}
      - --protected-mode ${protectedMode}
      - --dir ${dir}
      - --pidfile ${pidfile}
      - --logfile ${logfile}
      - --dbfilename ${dbfilename}
      - --appendonly ${appendonly}
      - --appendfilename ${appendfilename}
      - --requirepass ${password}
      - --masterauth ${password}
      - --cluster-enabled ${clusterEnabled}
      - --cluster-config-file ${clusterConfigFile}
      - --cluster-node-timeout ${clusterNodeTimeout}
      - --cluster-announce-ip  ${serverIp}

  redis2:
    image: registry.cn-beijing.aliyuncs.com/zbzly/redis
    env_file:
      - .env
    command:
      - redis-server
      - --port 6382
      - --cluster-announce-port 6382
      - --cluster-announce-bus-port 16382
      - --bind ${bind}
      - --protected-mode ${protectedMode}
      - --dir ${dir}
      - --pidfile ${pidfile}
      - --logfile ${logfile}
      - --dbfilename ${dbfilename}
      - --appendonly ${appendonly}
      - --appendfilename ${appendfilename}
      - --requirepass ${password}
      - --masterauth ${password}
      - --cluster-enabled ${clusterEnabled}
      - --cluster-config-file ${clusterConfigFile}
      - --cluster-node-timeout ${clusterNodeTimeout}
      - --cluster-announce-ip  ${serverIp}

    ports:
      - "6382:6382"
      - "16382:16382"
  redis3:
    image: registry.cn-beijing.aliyuncs.com/zbzly/redis
    env_file:
      - .env
    command:
      - redis-server
      - --port 6383
      - --cluster-announce-port 6383
      - --cluster-announce-bus-port 16383
      - --bind ${bind}
      - --protected-mode ${protectedMode}
      - --dir ${dir}
      - --pidfile ${pidfile}
      - --logfile ${logfile}
      - --dbfilename ${dbfilename}
      - --appendonly ${appendonly}
      - --appendfilename ${appendfilename}
      - --requirepass ${password}
      - --masterauth ${password}
      - --cluster-enabled ${clusterEnabled}
      - --cluster-config-file ${clusterConfigFile}
      - --cluster-node-timeout ${clusterNodeTimeout}
      - --cluster-announce-ip  ${serverIp}

    ports:
      - "6383:6383"
      - "16383:16383"
  redis4:
    image: registry.cn-beijing.aliyuncs.com/zbzly/redis
    env_file:
      - .env
    command:
      - redis-server
      - --port 6384
      - --cluster-announce-port 6384
      - --cluster-announce-bus-port 16384
      - --bind ${bind}
      - --protected-mode ${protectedMode}
      - --dir ${dir}
      - --pidfile ${pidfile}
      - --logfile ${logfile}
      - --dbfilename ${dbfilename}
      - --appendonly ${appendonly}
      - --appendfilename ${appendfilename}
      - --requirepass ${password}
      - --masterauth ${password}
      - --cluster-enabled ${clusterEnabled}
      - --cluster-config-file ${clusterConfigFile}
      - --cluster-node-timeout ${clusterNodeTimeout}
      - --cluster-announce-ip  ${serverIp}
    ports:
      - "6384:6384"
      - "16384:16384"
  redis5:
    image: registry.cn-beijing.aliyuncs.com/zbzly/redis
    env_file:
      - .env
    command:
      - redis-server
      - --port 6385
      - --cluster-announce-port 6385
      - --cluster-announce-bus-port 16385
      - --bind ${bind}
      - --protected-mode ${protectedMode}
      - --dir ${dir}
      - --pidfile ${pidfile}
      - --logfile ${logfile}
      - --dbfilename ${dbfilename}
      - --appendonly ${appendonly}
      - --appendfilename ${appendfilename}
      - --requirepass ${password}
      - --masterauth ${password}
      - --cluster-enabled ${clusterEnabled}
      - --cluster-config-file ${clusterConfigFile}
      - --cluster-node-timeout ${clusterNodeTimeout}
      - --cluster-announce-ip  ${serverIp}
    ports:
      - "6385:6385"
      - "16385:16385"
  redis6:
    image: registry.cn-beijing.aliyuncs.com/zbzly/redis
    env_file:
      - .env
    command:
      - redis-server
      - --port 6386
      - --cluster-announce-port 6386
      - --cluster-announce-bus-port 16386
      - --bind ${bind}
      - --protected-mode ${protectedMode}
      - --dir ${dir}
      - --pidfile ${pidfile}
      - --logfile ${logfile}
      - --dbfilename ${dbfilename}
      - --appendonly ${appendonly}
      - --appendfilename ${appendfilename}
      - --requirepass ${password}
      - --masterauth ${password}
      - --cluster-enabled ${clusterEnabled}
      - --cluster-config-file ${clusterConfigFile}
      - --cluster-node-timeout ${clusterNodeTimeout}
      - --cluster-announce-ip  ${serverIp}
    ports:
      - "6386:6386"
      - "16386:16386"

.env

properties
#服务器ip
serverIp=192.168.152.200
#集群密码
password=123456
#开放连接
bind=0.0.0.0
#关闭保护模式
protectedMode=no
#文件存储目录
dir=/data
#pid文件
pidfile=/data/redis.pid
#日志文件
logfile=/data/redis.log
#dump文件
dbfilename=dump.rdb
#开启aof
appendonly=yes
#aof文件
appendfilename=appendonly.aof
#开启集群
clusterEnabled=yes
#集群配置文件
clusterConfigFile=cluster.conf
#集群超时时间
clusterNodeTimeout=5000

初始化集群

bash
redis-cli -a 123456 --cluster create --cluster-replicas 1 192.168.152.200:6381 192.168.152.200:6382 \
192.168.152.200:6383 192.168.152.200:6384 192.168.152.200:6385 192.168.152.200:6386

集群要求最少三个节点 指定从节点为1则至少需要6个(3+3*1)节点

若初始化未成功返回信息可能是节点无法通信