zoukankan      html  css  js  c++  java
  • redis-sentinel-cluster-codis

    • redis-主从复制是redis分布式的基础,redis的高可用离开了主从复制将无法进行
    • sentinel是redis高可用的一种解决方案
      • 由一个或者多个sentinel实例组成的sentinel系统可以监视任意多个主服务器以及主服务器下属的从服务器
      • 并且在被监视的主服务器进入下线状态时,自动将下线主服务器下属的某个从服务器升级为新的主服务器
      • 然后由新的主服务器代替已经下线的主服务器继续执行命令请求
      • 图一是正常状态下的sentinel体系,sentinel系统监视所有主从节点

        • sentinel会向master建立两个异步网络连接:命令连接;_sentinel_:hello频道
        • sentinel每十秒一次通过命令连接获取主服务器以及从服务器信息
        • sentinel每两秒一次通过被监视服务器的_sentinel_:hello频道向其他sentinel宣告自己存在
        • sentinel之间只存在命令连接
      • 图二是当sentinel发现master挂掉的情况,主从复制会中断

        • 主观下线:少数派sentinel认为master下线
        • 客观下线:大多数sentinel认为master下线
      • 图三是sentinel开始执行容灾,会选择一个最优的slave节点升级为new-master节点设置新的主从关系,开始主从复制

        • sentinel会选举一个领头sentinel来对下线服务器之心个故障转移
        • 领头sentinel挑选一个最合理的slave(复制偏移量最大的节点)来晋升为new-master
        • 已下线的master的所有slave都连接new-master开始主从复制
      • 图四是当old-master重启后会被作为新的slave节点挂在master下,执行主从同步复制

    总结:

    sentinel是在主从复制的基础上实现了对节点的监控和容灾,解决了主从复制模型中,无法自动容灾的问题

    sentinel是运行在特殊模式下的redis服务器,使用与普通redis服务器不同的命令表

    sentinel使用raft多数派选举算法来判定master下线,来执行选举,确保了不会出现脑裂的风险

    sentinel最小数目三台,可以保证最基础的可用性容错性

    redis-cluster

    • sentinel模型虽然提供了高可用的保障,但是在大数据高并发下,单个redis实例闲的捉襟见肘
    • 首先在内存上,单个redis内存不宜过大,否则会导致rdb文件过大
      • 导致主从同步复制时全量复制时间过长;在实例重启恢复时也会消耗很长的数据加载时间
    • 其次在cpu利用率上,单个redis实例只能利用单个核心
      • 在多核的背景下,浪费机器资源;并且单个核心完成海量数据存取压力也很大

    综上所述,redis集群方案就显得很重要,集群可以将众多小内存redis实例整合起来,将分布在多台机器上的cpu核心运算能力聚集起来,完成海量数据存储和高并发读写操作

    redis集群是通过分片(sharding)来进行数据共享,并且提供复制和故障转移功能

    redis是去中心化的集群模型

    集群节点cluster-node

    • node是组成集群的基本单位,就是一个运行在集群模式下的redis服务器,redis服务器会在启动时根据cluster-enabled配置选项是否为yes来决定是否开启集群模式
    • 集群中节点在集群运行中会继续使用单机模式中的服务器组件:

      • 节点会继续使用文件事件来处理命令请求和命令回复
      • 节点会继续使用时间事件通过serverCron来处理周期任务;集群模式下serverCron函数会执行集群的clusterCron函数
      • 节点依旧可以使用rdb或者aof持久化方式来实现redis数据持久化
      • 节点依旧使用发布订阅模块来执行publish,subscribe命令
      • 节点会继续使用复制模块进行节点的复制工作

    集群分片-槽指派

    redis集群通过分片的方式来保存数据库中的键值对:

    • 集群的整个数据库被分为16384个槽(slot)
    • 数据库中的每个key都属于这16384个槽中的一个
    • 集群中每个节点都可以处理最少0个最多16384个槽(slot)
    • 当数据库中的16384个槽都有节点处理-集群处于上线状态
    • 当数据库中有任意一个槽没有得到节点处理-集群处于下线状态

    槽定位:

    • cluster默认会对key值使用crc16算法进行hash得到一个整数值
    • 然后用这个整数对16383进行取模得到具体槽位
    • cluster允许用户强制某个key挂在特定的槽位上
    • 当客户端向节点发送数据库命令时,接受命令的节点会计算出命令要处理的数据库属于哪个槽,并且检查这个歌槽是否指派给了自己

      • 如果key所在的槽正好指派到了当前节点,那么节点直接执行命令
      • 如果key所在槽未指派给当前节点,节点会向客户端返回一个moved错误,指引客户端转向正确节点执行命令

    节点数据库

    • 集群节点保存键值对以及键值对过期的方式与单机redis服务器对键值对以及过期处理方式完全相同
    • 集群节点只能使用0号数据库,而单机数据库没有这种限制
    • 集群节点会使用clusterState结构中的slots_to_keys跳跃表来保存slot与key的关系

    总结

    redis-cluster是一个去中心化的集群,每个单独节点都与单机redis节点功能一致

    redis-cluster基于分片实现数据共享,一共16384个槽对应集群中的主节点

    redis-cluster中slot对应的是master-node节点,slave-node只负责与master同步复制

    redis-cluster中主节点失效,会从slave中选择合理slave晋升为新master

    codis

    • codis是一个无状态的转发代理中间件
    • 可以启动多个codis实例供client使用
    • 每个codis节点是对等的
    • 单个codis代理能支撑的qps有限
      • 通过启动多个codis代理科显著增加整体qps需求
      • 还可以起到容灾功能

    codis分片原理

    • codis默认将所有key划分为1024个槽位
    • 首先会对key做crc32计算hash值
    • 然后将hash值对1024取模得到余数
    • 这个余数就是key对应槽位
    • 每个槽位之后都会唯一映射到后面的多个redis实例之一
    • codis会在内存中维护槽位和redis实例的关系

    槽位同步:

    • codis默认将槽位映射关系保存在内存中,那么不同codis实例之间槽位关系就无法同步
    • 所以codis使用zookeeper来持久化槽位关系
    • 当槽位关系发生变化,codis-proxy会监听到变化并重新同步槽位关系

    codis扩容

    • 当codis单实例时,所有1024个槽位都指向同一个redis实例
    • 当单实例需要扩容时,就需要将一半的slot指向新的redis实例
    • codis会遍历扫描出戴迁移槽位的所有key然后挨个迁移到新redis节点
    • 当迁移过程中时,codis依旧收到新的请求打在正在迁移的槽位上
      • 此时该槽位上数据同时处于新旧两个槽位中,codsi无法判断key在具体哪个实例
      • 所以codis接受到处于迁移槽位中的key后,会强制对当前key迁移
      • 迁移完成再将命令请求转发到新的redis实例

    codis缺点:

    • key分散在不同的实例,所以不支持事务
    • 增加leproxy作为中转层所以网络开销会变大
    • 使用zk增加了运维成本
  • 相关阅读:
    AO-XXXX
    最基础的rpm命令
    yum插件
    adjtimex修改tick值用法举例
    [工具]iostat
    chrony配置介绍
    CentOS / RHEL 7 : Chrony V/s NTP (Differences Between ntpd and chronyd)
    NTP测试1
    shell使用eval进行赋值bc计算,bad substitution
    Free中的buffer和cache理解
  • 原文地址:https://www.cnblogs.com/cavaliersyb/p/12029017.html
Copyright © 2011-2022 走看看