Redis-Cluster

即使是使用哨兵,

  • 此时的Redis集群的每个数据库依然存有集群中的所有数据,
    • 从而导致集群的总数据存储量受限于可用存储内存最小的节点,形成了木桶效应
    • 而因为Redis是基于内存存储的,
      • 所以这一个问题在redis中就显得尤为突出了
  • 在redis3.0之前,
    • 我们是通过在客户端去做的分片,
    • 通过hash环的方式对key进行分片存储
  • 分片虽然能够解决各个节点的存储压力,
    • 但是导致维护成本高、增加、移除节点比较繁琐。
  • 在redis3.0之后,支持集群功能,
    • 集群的特点在于拥有和单机实例一样的性能,
    • 同时在网络分区以后能够提供一定的可访问性
      • 以及对主数据库故障恢复的支持。
  • 哨兵和集群是两个独立的功能
    • 不需要对数据进行分片使用哨兵就够了,
    • 如果要进行水平扩容集群是一个比较好的方式

拓扑结构

  • 一个Redis Cluster由多个Redis节点构成
  • 每个一节点组对应数据sharding的一个分片
  • 节点组内部分为主备两类节点,对应master和slave节点
    • 两者数据准实时一致,通过异步化的主备复制机制来保证
    • 一个节点组有且只有一个master节点,
      • 同时可以有0到多个slave节点,
      • 在这个节点组中只有master节点对用户提供写服务
      • 读服务可以由master或者slave提供
  • redis-cluster是基于gossip协议实现的无中心化节点的集群,
    • 因为去中心化的架构不存在统一的配置中心,
    • 各个节点对整个集群状态的认知来自于节点之间的信息交互
      • 在Redis Cluster,这个信息交互是通过Redis Cluster Bus来完成的

Redis的数据分区

  • 分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,
    • 即把数据集划分到多个节点上,
    • 每个节点负责整个数据的一个子集,
    • Redis Cluster采用哈希分区规则,采用虚拟槽分区。
  • 虚拟槽分区巧妙地使用了哈希空间,
    • 使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合
      • 整数定义为槽(slot)。
    • 比如Redis Cluster槽的范围是0 ~ 16383。
    • 槽是集群内数据管理和迁移的基本单位。
    • 采用大范围的槽的主要目的
      • 为了方便数据的拆分和集群的扩展,
      • 每个节点负责一定数量的槽
    • 计算公式:slot = CRC16(key)%16383。
      • 每一个节点负责维护一部分槽以及槽所映射的键值数据。

36c86a0a134e8b6a82649f64fbc64830a74.jpg

HashTags

  • 我们希望对相关联的业务以原子方式进行操作
  • 举个简单的例子
    • 在单节点上执行MSET , 它是一个原子性的操作
    • 但是在集群环境下,我们仍然可以执行MSET命令,
      • 但它的操作不在是原子操作,
      • 会存在某些指定的key被更新,
      • 而另外一些指定的key没有改变,
      • 原因是多个key可能会被分配到不同的机器上。
    • 这里就会存在一个矛盾点,
      • 要求key尽可能的分散在不同机器,
      • 又要求某些相关联的key分配到相同机器。
    • 这个也是在面试的时候会容易被问到的内容。
      • 怎么解决呢?
        • 我们需要考虑如何让相关联的key得到的hash值都相同
        • 在redis中引入了HashTag的概念,
          • 可以使得数据分布算法可以根据key的某一个部分进行计算,
          • 然后让相关的key落到同一个数据分片
      • 举个简单的例子,
        • 加入对于用户的信息进行存储,
          • user:user1:id、user:user1:name/
          • 那么通过hashtag的方式,user:{user1}:id、user:{user1}.name;
          • 表示当一个key包含 {} 的时候,
          • 就不对整个key做hash,而仅对 {} 包括的字符串做hash。
          • user1 代表关联

重定向客户端

  • Redis Cluster并不会代理查询,
    • 那么如果客户端访问了一个key并不存在的节点,
    • 这个节点是怎么处理的呢?
      • 那么就会返回客户端下面信息:
        • -MOVED 254 127.0.0.1:6381
          • 表示客户端想要的254槽由运行在IP为127.0.0.1,端口为6381的Master实例服务。
    • 如果根据key计算得出的槽恰好由当前节点负责,
      • 则当期节点会立即返回结果

分片迁移

  • 在一个稳定的Redis cluster下,
    • 每一个slot(槽)对应的节点是确定的,
    • 但是在某些情况下,节点和分片对应的关系会发生变更
      • \1. 新加入master节点
        \2. 某个节点宕机
  • 也就是说当动态添加或减少node节点时,
    • 需要将16384个槽做个再分配,槽中的键值也要迁移。
    • 当然,这一过程,在目前实现中,还处于半自动状态,需要人工介入。
  • 新增一个主节点
    • 新增一个节点D,redis cluster的这种做法是从各个节点的前面各拿取一部分slot到D上。大致就会变成这样:
      节点A覆盖1365-5460
      节点B覆盖6827-10922
      节点C覆盖12288-16383
      节点D覆盖0-1364,5461-6826,10923-12287
  • 删除一个主节点
    • 先将节点的数据移动到其他节点上,然后才能执行删除

槽迁移的过程

  • 槽迁移的过程中有一个不稳定状态,
    • 这个不稳定状态会有一些规则,
    • 这些规则定义客户端的行为,
    • 从而使得RedisCluster不必宕机的情况下可以执行槽的迁移
  • 下面这张图描述了我们迁移编号为1、2、3的槽的过程中,
    • 他们在MasterA节点和MasterB节点中的状态。
    • 2d49ff1e39bff8e0b9858cd768b73ca9989.jpg
    • 简单的工作流程
      • 向MasterB发送状态变更命令,
        • 把Master B对应的slot状态设置为IMPORTING(引入)
      • 向MasterA发送状态变更命令,
        • 将Master对应的slot状态设置为MIGRATING(迁徙)
    • 当MasterA的状态设置为MIGRANTING后,
      • 表示对应的slot正在迁移,
      • 为了保证slot数据的一致性,
      • MasterA此时对于slot内部数据提供读写服务的行为和通常状态下是有区别的
        • MIGRATING(迁徙)状态
          • \1. 如果客户端访问的Key还没有迁移出去,则正常处理这个key
            \2. 如果key已经迁移或者根本就不存在这个key,则回复客户端ASK信息让它跳转到MasterB去执行
        • IMPORTING(引入)状态
          • 对于MasterB上的slot上的所有非ASK跳转过来的操作MasterB都不会处理,
            • 而是通过MOVED命令让客户端跳转到MasterA上去执行
          • 这样的状态控制保证了同一个key在迁移之前总是在源节点上执行迁移后总是在目标节点上执行
            • 防止出现两边同时写导致的冲突问题。
          • 而且迁移过程中新增的key一定会在目标节点上执行
            • 源节点也不会新增key,
            • 是的整个迁移过程既能对外正常提供服务,
            • 又能在一定的时间点完成slot的迁移。

转载于:https://my.oschina.net/u/3847203/blog/3024607

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值