Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片

Redis学习笔记—Redis的分区的意义与方式,官方Cluster分区集群分片

1.分片简介

  1. 不同节点分组服务于相互无交集的分片(sharding),Redis Cluster 不存在单独的proxy或配置服务器,所以需要将客户端路由到目标的分片。
  2. Redis分片---客户端路由:Redis Cluster的客户端相比单机Redis 需要具备路由语义的识别能力,且具备一定的路由缓存能力。

2.Redis分片重定向方式—moved重定向

  1. moved重定向图解如下:
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片
  2. 每个节点通过通信都会共享Redis Cluster中槽和集群中对应节点的关系
  3. 客户端向Redis Cluster的任意节点发送命令,接收命令的节点会根据CRC16规则进行hash运算与16384取余,计算自己的槽和对应节点
  4. 如果保存数据的槽被分配给当前节点,则去槽中执行命令,并把命令执行结果返回给客户端
  5. 如果保存数据的槽不在当前节点的管理范围内,则向客户端返回moved重定向异常
  6. 客户端接收到节点返回的结果,如果是moved异常,则从moved异常中获取目标节点的信息
  7. 客户端向目标节点发送命令,获取命令执行结果

3.Redis分片重定向方式—ask重定向

  1. ask重定向图解如下:
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片
  2. 在对集群进行扩容和缩容时,需要对槽及槽中数据进行迁移
  3. 当客户端向某个节点发送命令,节点向客户端返回moved异常,告诉客户端数据对应的槽的节点信息,如果此时正在进行集群扩展或者缩空操作,当客户端向正确的节点发送命令时,槽及槽中数据已经被迁移到别的节点了,就会返回ask,这就是ask重定向机制
  4. 客户端向目标节点发送命令,目标节点中的槽已经迁移支别的节点上了,此时目标节点会返回ask转
    向给客户端
  5. 客户端向新的节点发送Asking命令给新的节点,然后再次向新节点发送命令
  6. 新节点执行命令,把命令执行结果返回给客户端

4. moved和ask的区别

  1. moved:槽已确认转移
  2. ask:槽还在转移过程中,也就是说ask重定向只会出现在扩容/缩容时

5. Smart智能客户端—JedisCluster

  1. JedisCluster是Jedis根据RedisCluster的特性提供的集群智能客户端
  2. JedisCluster为每个节点创建连接池,并跟节点建立映射关系缓存(Cluster slots)
  3. JedisCluster将每个主节点负责的槽位一一与主节点连接池建立映射缓存
  4. JedisCluster启动时,已经知道key,slot和node之间的关系,可以找到目标节点
  5. JedisCluster对目标节点发送命令,目标节点直接响应给JedisCluster
  6. 如果JedisCluster与目标节点连接出错,则JedisCluster会知道连接的节点是一个错误的节点,此时节点返回moved异常给JedisCluster
  7. JedisCluster会重新初始化slot与node节点的缓存关系,然后向新的目标节点发送命令,目标命令执行命令并向JedisCluster响应
  8. 如果命令发送次数超过5次,则抛出异常"Too many cluster redirection!"
  9. 过程图如下:
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片
  10. 代码过程如下,最终是将节点和线程池放到一起进行工作
JedisPoolConfig config = new JedisPoolConfig(); 
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>(); 
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7001)); 
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7002)); 
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7003)); 
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7004)); 
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7005)); 
jedisClusterNode.add(new HostAndPort("192.168.127.128", 7006)); 
JedisCluster jcd = new JedisCluster(jedisClusterNode, config); 
jcd.set("name:001","zhangfei"); 
String value = jcd.get("name:001");

6. Redis分片—迁移

  1. 在RedisCluster中每个slot 对应的节点在初始化后就是确定的。在某些情况下,节点和分片需要变更,如以下情况
    1. 新的节点作为master加入;
    2. 某个节点分组需要下线;
    3. 负载不均衡需要调整slot 分布。
  2. 此时需要进行分片的迁移,迁移的触发和过程控制由外部系统完成。包含下面 2 种
    1. 节点迁移状态设置:迁移前标记源/目标节点。
    2. key迁移(数据的迁移)的原子化命令:迁移的具体步骤。

7. key迁移(数据的迁移)的具体步骤

Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片

  1. 向节点B发送状态变更命令,将B的对应slot 状态置为importing。
  2. 向节点A发送状态变更命令,将A对应的slot 状态置为migrating。
  3. 向A 发送migrate 命令(原子化的迁移命令),告知A 将要迁移的slot对应的key 迁移到B。
  4. 当所有key 迁移完成后,cluster setslot 重新设置槽位。

7. Redis分片—扩容

  1. 创建主节点:先创建一个主节点7007
  2. 添加7007结点作为新节点,并启动执行命令:./redis-cli --cluster add-node 192.168.72.128:7007 192.168.72.128:7001
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片
  3. 查看节点信息,如下所示:7007没有链接,因为没有分槽
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片

8.hash槽重新分配(数据迁移)

  1. 分槽的过程也是数据迁移的过程
  2. 添加完主节点需要对主节点进行hash槽分配,这样该主节才可以存储数据。
  3. 给刚添加的7007结点分配槽

9.hash槽重新分配(数据迁移)步骤

  1. 连接上集群(连接集群中任意一个可用结点下进行分槽命令都行)
    ./redis-cli --cluster reshard 192.168.72.128:7007
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片
  2. 输入要分配的槽数量:输入3000表示要给目标节点分配3000个槽
    How many slots do you want to move (from 1 to 16384)? 3000
    
  3. 输入接收槽的结点id:下图红色框部分是节点id
    What is the receiving node ID?
    
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片
  4. 输入源结点id:输入all,表示从所有主节点中分出一部分节点到当前主节点中
    Please enter all the source node IDs. 
    Type 'all' to use all the nodes as source nodes for the hash slots. 
    Type 'done' once you entered all the source nodes IDs.
    

10.给新扩容的主节点添加从节点

  1. 添加7008从结点,将7008作为7007的从结点
  2. 命令:./redis-cli --cluster add-node 新节点的ip和端口 旧节点ip和端口 --cluster-slave -- cluster-master-id 主节点id
  3. 例如:./redis-cli --cluster add-node 192.168.72.128:7008 192.168.72.128:7007 -- cluster-slave --cluster-master-id 6ff20bf463c954e977b213f0e36f3efc02bd53d6
  4. 下图中红色框部分是master-id
  5. 寻找节点id可以去任何一个节点下的nodes.conf文件中去寻找
    Redis学习笔记---Redis的分区的意义与方式,官方Cluster分区集群分片

11.缩容

  1. 命令:./redis-cli --cluster del-node 127.0.0.1:7008 6be94480315ab0dd2276a7f70c82c578535d6666
  2. 节点后的的字符串表示该节点的节点id
  3. 删除已经占有hash槽的结点会失败,报错如下:解决报错就需要将该结点占用的hash槽分配出去。
    [ERR] Node 192.168.127.128:7008 is not empty! Reshard data away and try again.
    
  4. 并且删除节点后,该节点将自动关闭
上一篇:openresty应用场景以及研发网关系统功能说明


下一篇:可根据配置文件变化自动reload的openresty docker镜像制作