1.单节点redis的缺陷
  • 单点故障导致服务不可用
  • redis的容量优先
  • redis的服务压力
2. 集群的AKF原则

AKF原则

centos redis 集群 redis集群 cap_redis

x轴:全量,镜像

Y轴:业务,功能

Z轴:优先级,逻辑再拆分

2.1 redis使用AKF原则扩展为集群产生的问题

通过AKF一变多 :数据一致性问题

X轴:redis的主从复制

y轴:redis的集群

z轴:redis的集群(根据用户需求)


centos redis 集群 redis集群 cap_centos redis 集群_02

3. CAP原则

CAP原则百科

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

4. Redis的复制(同步)

redis的复制

Redis使用默认的异步复制,其特点是低延迟和高性能,是绝大多数 Redis 用例的自然复制模式。但是,从 Redis 服务器会异步地确认其从主 Redis 服务器周期接收到的数据量。

主从模式,从节点不支持写入,如果主节点宕机,这个集群就会失去写的能力,不具备自动容错和恢复功能。

redis搭建读写分离的时候,当连接到从节点发生写操作的时候,命令会默认重定向到主节点去

4.1. redis复制的重要细节
  • Redis 使用异步复制,slave 和 master 之间异步地确认处理的数据量
  • 一个 master 可以拥有多个 slave
  • slave 可以接受其他 slave 的连接。除了多个 slave 可以连接到同一个 master 之外, slave 之间也可以像层叠状的结构(cascading-like structure)连接到其他 slave 。自 Redis 4.0 起,所有的 sub-slave 将会从 master 收到完全一样的复制流。
  • Redis 复制在 master 侧是非阻塞的。这意味着 master 在一个或多个 slave 进行初次同步或者是部分重同步时,可以继续处理查询请求。
  • 复制在 slave 侧大部分也是非阻塞的。当 slave 进行初次同步时,它可以使用旧数据集处理查询请求,假设你在 redis.conf 中配置了让 Redis 这样做的话。否则,你可以配置如果复制流断开, Redis slave 会返回一个 error 给客户端。但是,在初次同步之后,旧数据集必须被删除,同时加载新的数据集。 slave 在这个短暂的时间窗口内(如果数据集很大,会持续较长时间),会阻塞到来的连接请求。自 Redis 4.0 开始,可以配置 Redis 使删除旧数据集的操作在另一个不同的线程中进行,但是,加载新数据集的操作依然需要在主线程中进行并且会阻塞 slave 。
  • 复制既可以被用在可伸缩性,以便只读查询可以有多个 slave 进行(例如 O(N) 复杂度的慢操作可以被下放到 slave ),或者仅用于数据安全。
  • 可以使用复制来避免 master 将全部数据集写入磁盘造成的开销:一种典型的技术是配置你的 master Redis.conf 以避免对磁盘进行持久化,然后连接一个 slave ,其配置为不定期保存或是启用 AOF。但是,这个设置必须小心处理,因为重新启动的 master 程序将从一个空数据集开始:如果一个 slave 试图与它同步,那么这个 slave 也会被清空。
Redis 复制功能的细节过程

master 开启一个后台保存进程,以便于生产一个 RDB 文件。同时它开始缓冲所有从客户端接收到的新的写入命令。当后台保存完成时, master 将数据集文件传输给 slave, slave将之保存在磁盘上,然后加载文件到内存。再然后 master 会发送所有缓冲的命令发给 slave。这个过程以指令流的形式完成并且和 Redis 协议本身的格式相同。

你可以用 telnet 自己进行尝试。在服务器正在做一些工作的同时连接到 Redis 端口并发出 SYNC 命令。你将会看到一个批量传输,并且之后每一个 master 接收到的命令都将在 telnet 回话中被重新发出。事实上 SYNC 是一个旧协议,在新的 Redis 实例中已经不再被使用,但是其仍然向后兼容:但它不允许部分重同步,所以现在 PSYNC 被用来替代 SYNC。

centos redis 集群 redis集群 cap_服务器_03

5. Redis中哨兵sentinel

Redis 的 Sentinel 文档

centos redis 集群 redis集群 cap_Redis_04

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器

在此时sentinel集群会在内部先选举出一个leader,然后由这个leader对集群中某个出现问题的主master进行故障迁移(选出从节点当master)

客观下线和主观下线
  • 主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
  • 客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断。 (一个 Sentinel 可以通过向另一个 Sentinel 发送 SENTINEL is-master-down-by-addr 命令来询问对方是否认为给定的服务器已下线。)

客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件。

从主观下线状态切换到客观下线状态并没有使用严格的法定人数算法(strong quorum algorithm), 而是使用了流言协议: 如果 Sentinel 在给定的时间范围内, 从其他 Sentinel 那里接收到了足够数量的主服务器下线报告, 那么 Sentinel 就会将主服务器的状态从主观下线改变为客观下线。 如果之后其他 Sentinel 不再报告主服务器已下线, 那么客观下线状态就会被移除。

6.Redis集群

redis集群教程

Redis集群的拆分方案
  • 数据可以分类,交集不多
  • 数据没办法拆分,用一致性hash算法进行拆分(redis-cluster)

centos redis 集群 redis集群 cap_redis_05

centos redis 集群 redis集群 cap_centos redis 集群_06

一致性hash算法

希算法就是将任意长度的二进制值映射为较短的固定长度的唯一的二进制值(即哈希值)。敲黑板,哈希算法的入参可以是任意长度,而出参是固定长度而且唯一。一致性哈希算法就是,先构造一个0到2^32的整数环(hash环,java中可用SortedMap实现),根据缓存服务器名称(也可以是ip:port)计算出hash值,根据其hash值将缓存服务器放置在hash环上。每次根据要缓存的key计算得到hash值,在hash环上顺时针查找距离最近的缓存服务器节点(SortedMap.tailMap(key)实现),进行set/set操作

centos redis 集群 redis集群 cap_redis_07

一致性hash算法的问题

1.加减缓存服务器节点会造成hash环部分数据无法命中;

2.少量缓存服务器节点时,数据分布不均匀,同时缓存服务器节点变化将影响大范围数据;

3.普通的一致性哈希分区需要增加一倍或减掉一半缓存服务器节点才能保持数据负载均衡;

当只有少量缓存服务器又想尽量保证负载均衡时,我们一般采用下面的办法:将一个缓存服务器节点虚拟成一组,比如某台缓存服务器为192.168.2.1:6379,我们就可以将其虚拟成一个虚拟节点数组,为192.168.2.1:6379-1,192.168.2.1:6379-2,192.168.2.1:6379-3……然后分别计算数组里的元素的hash值并映射到hash环上,每台缓存服务器都如此处理。当不同key的缓存路由到虚拟节点时,最终都是指向真实的缓存服务器节点。通过这样增加节点的方式,可以一定概率上使数据路由均衡

redis-cluster

Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。

其结构特点:

1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。

2、节点的fail是通过集群中超过半数的节点检测失效时才生效。

3、客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

4、redis-cluster把所有的物理节点映射到[0-16383]slot上(不一定是平均分配),cluster 负责维护node<->slot<->value。

5、Redis集群预分好16384个桶,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。

a.redis cluster节点分配
现在我们是三个主节点分别是:A, B, C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:

  • 节点A覆盖0-5460;
  • 节点B覆盖5461-10922;
  • 节点C覆盖10923-16383.
    获取数据:
    如果存入一个值,按照redis cluster哈希槽的算法: CRC16('key')384 = 6782。 那么就会把这个key 的存储分配到 B 上了。同样,当我连接(A,B,C)任何一个节点想获取'key'这个key时,也会这样的算法,然后内部跳转到B节点上获取数据
    新增一个主节点:
    新增一个节点D,redis cluster的这种做法是从各个节点的前面各拿取一部分slot到D上,我会在接下来的实践中实验。大致就会变成这样:
  • 节点A覆盖1365-5460
  • 节点B覆盖6827-10922
  • 节点C覆盖12288-16383
  • 节点D覆盖0-1364,5461-6826,10923-12287

同样删除一个节点也是类似,移动完成后就可以删除这个节点了。

b.Redis Cluster主从模式
redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉

上面那个例子里, 集群有ABC三个主节点, 如果这3个节点都没有加入从节点,如果B挂掉了,我们就无法访问整个集群了。A和C的slot也无法访问。

所以我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像这样, 集群包含主节点A、B、C, 以及从节点A1、B1、C1, 那么即使B挂掉系统也可以继续正确工作。

B1节点替代了B节点,所以Redis集群将会选择B1节点作为新的主节点,集群将会继续正确地提供服务。 当B重新开启后,它就会变成B1的从节点。

不过需要注意,如果节点B和B1同时挂了,Redis集群就无法继续正确地提供服务了

8.Redis集群的代理

centos redis 集群 redis集群 cap_centos redis 集群_08

redis cluster代理

目前市面上主流的代理包含:predixy、twemproxy、codis、redis-cerberus四款,这四款各有各的优势,我们逐个对比进行对比分析。

特性

predixy

twemproxy

codis

redis-cerberus

高可用

Redis Sentinel或Redis Cluster

一致性哈希

Redis Sentinel

Redis Cluster

可扩展

Key哈希分布或Redis Cluster

Key哈希分布

Key哈希分布

Redis Cluster

开发语言

C++

C

GO

C++

多线程





事务

Redis Sentinel模式单Redis组下支持

不支持

不支持

不支持

BLPOP/BRPOP/BLPOPRPUSH

支持

不支持

不支持

支持

Pub/Sub

支持

不支持

不支持

支持

Script

支持load

不支持

不支持

不支持

Scan

支持

不支持

不支持

不支持

Select DB

支持

不支持

支持

Redis Cluster只有一个DB

Auth

支持定义多个密码,给予不同读写及管理权限和Key访问空间

不支持

同redis

不支持

读从节点

支持,可定义丰富规则读指定的从节点

不支持

支持,简单规则

支持,简单规则

多机房支持

支持,可定义丰富规则调度流量

不支持

有限支持

有限支持

统计信息

丰富

丰富

丰富

简单

知白守黑,和光同尘