zoukankan      html  css  js  c++  java
  • Redis集群的三种模式

    Redis是什么

    Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:

    ·         基于内存运行,性能高效

    ·         支持分布式,理论上可以无限扩展

    ·         key-value存储系统

    ·         开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API

     

    -主从(master-salver2.8之前

    redismysql一样,虽然读写都很快,但是也会产生读写压力大的情况。为了分担读的压力,Redis支持主从复制,master进行写操作,slave进行读操作。Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步

     

    -哨兵(sentinel2.8之后

    由于redis单一的主从复制模式下,容灾性较差,当集群中master由于故障下线了,那么slaver因为没有master而同步中断,因而需要人工进行故障转移工作。

    Redis2.8之后的版本提供了一种高可用的方案——哨兵模式(Sentinel),由一个或者多个哨兵节点组成Sentinel系统用于监听一个或多个redis集群,监听群内主节点以及其从节点服务提供状态,并且当监听的redis集群中master下线后,从master的从属节点中选举出新的master并维护新的主从关系。

    注:哨兵监视redis集群的同时,哨兵节点之间也会相互监听。


    哨兵模式过程

    1、监听

    sentinel在监听redis的集群过程中会周期性的对redis集群发送指令进行状态监控

    周期

    消息类型

    动作

    方向

    作用

    10s

    info命令

    哨兵每隔10s向监听的redis集群所有节点发送info命令

    sentinel --> master

    sentinel --> slave

    1、通过info指令定期更新当前节点最新的节点信息

    2、发现新加入的slave节点,确认其主从关系

    2s

    sentinel:hello订阅

    master节点上会发布一个由哨兵订阅的频道,哨兵每隔2s发送自己的信息以及主节点判断到频道上

    sentinel --> master

    1、所有的sentinel都会订阅该频道,sentinel通过该频道相互发现,同时建立连接与监听

    2sentinel之间会交换对主节点的状态,为后续领导选举与客观下线做准备

    1s

    PING - PONG

    1s会对每个masterslavesentinel发送心跳包

    sentinel --> master

    sentinel --> slave

    sentinel --> sentinel

    1、实现了对每个节点的监控,是sentinel对节点判断是否下线的依据

     

     

    2、主观下线与客观下线

    sentinel集群在监听redis集群的过程中,每个哨兵会对master发送心跳PING来确认master的存活,如果master在“一定时间范围”内不回应PONG,或者回应了一个错误的消息,该sentinel会认为当前集群的master已经无法使用(主观下线),并同时向sentinel集群中的其他节点发送sentinel ismaster-down-by-addr命令询问其他节点对主机的状态判断,当超过一定数量的sentinel确认master已经无法使用,这时候master下线的判定就认为是客观的。

    注:客观下线后故障转移决定需要由sentinel中的leader进行裁决,sentinel在发送is-master-down-by-addr的同时使用Raft实现leader选举


    3、领导者选举

    1)每个在线的Sentinel节点都有资格成为领导者,当它确认主节点主观下线时候,会向其他Sentinel节点发送sentinel is-master-down-by-addr命令, 要求将自己设置为领导者

    2)收到命令的Sentinel节点,如果没有同意过其他Sentinel节点的sentinel is-master-down-by-addr命令,将同意该请求,否则拒绝

    3)如果该Sentinel节点发现自己的票数已经大于等于max(quorum,num(sentinels)/2+1),那么它将成为领导者

    4)如果此过程没有选举出领导者,将进入下一次选举

     

     

    4、故障转移

    故障转移就是当master宕机,sentinel集群会在redis集群中,自动选择一个合适的slave节点来升级为master节点的操作,不需要人工故障转移。

     1、筛选slave成为master

    1)过滤掉无法使用的slave(主观下线,断线)未回复Sentinel节点Pong相应的节点;

    2)选择slave-priority最大的从节点(可能存在多个相同大小),如果只存在一个,则完成选择,否则继续;

    slave-priority值在redis启动文件中配置,用于决定故障转移优先级,以及数据备份时的备份顺序;

    3)选择复制偏移量最大的从节点(复制最完整的)如果存在,则完成选择,否则继续;

    redis集群中slavemaster同步时,每台slave进与redis同步并非完全同步,不同slave同步master的进度可能不一致,在info relication中存在一项参数 master_repl_offset(复制偏移量)来表记录主从同步的程度,每完成一次同步此值会进行累加,从多个slave中选择偏移量最大的slave则能选出复制maste最完整的主机;

    作用:通过对比主从节点的复制偏移量,可以判断主从节点数据是否一致。可以通过主节点的统计信息,计算出master_repl_offset-slave_offset字节量,判断主从节点复制相差的数据量,根据这个差值判定当前复制的健康度。如果主从之间复制偏移量相差较大,则可能是网络延迟或命令阻塞等原因引起

    4)选择runid(服务器运行的唯一ID)最小的从节点;

    2、对新master发送 slaveof no one 指令,停止其主从复制

    3、修改程序段连接到新的master

    4、向集群中其他slave发送指令修改为新master的从机

    5、原master重启后修改为新masterslave


    缺点:

    1、如果是从节点下线了,sentinel是不会对其进行故障转移的,连接从节点的客户端也无法获取到新的可用从节点

    2、较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

    3、集群中只有一个主节点,当写操作并发量特别大的时候,并无法缓解写操作的压力

     

    -集群(cluster3.0之后

    为了解决Redis高可用模式下集群动态扩容困难、写操作并发瓶颈问题,在3.0之后redis推出了Redis-Cluster集群模式。

    redis-cluster采用无中心结构,每个节点保存各自的数据和整个集群的状态,每个节点都和其他所有节点连接,客户端连接任意主节点可以对整个集群中数据进行读写,所有的slave节点仅用于数据备份与故障转移。 


    raft集群至少需要奇数个节点,所以至少需要3redis作为集群中的master节点,而为了实现高可用(避免挂一台导账集群无法使用)每个master至少需要一个slave来进行主从复制,所以一个redis-Cluster集群至少需要六台机器。

     

    分布式存储

    redis-Cluster集群采用分布式存储的机制,每个master以及其slave只存储自己节点下的数据,客户端与任意master节点进行读写操作,会通过cluster的集群算法路由到对应的机器上【一致性哈希算法】。

    一致性哈希算法简单的来说就是,redis-cluster把所有的redis节点映射到[0-16383]slot上(不一定是平均分配,图示中物理机的哈希值为54611092216383),每一次读写操作集群会计算key的哈希值,然后根据哈希值选择对应机器进行读写。

    [0-16383]slot进行首尾相连,形成哈希环,对于每个redis节点会分配到一个值,该节点就负责自己节点值到上一节点值的所有slot值数据的存储。

    当集群要对一个key进行读写的时候,将key值计算出来的hash值向16384进行取模,将模值放入哈希环,并向后寻找第一个redisslot值,然后将key值存入redis上。


    通过这种方式,能够保证集群中存在多台master同时进行写操作,极大的降低了单节点高并发写的压力。

     

    动态扩容

    redis-cluster集群的一致性哈希算法支持动态扩容。动态扩容在一致性算法中涉及到两个问题,slot桶的重新分配、数据转移。


    上图所示是一个3节点redis-cluster集群里,redsi节点与key在哈希环上的映射关系,可以看出12两个key会存储在redis1上,3456四个key会存储在redis2上,而redis3只存储了key7。当我们需要往集群中新增一台redis,如果改变了全部redis分配的slot,那么数据的转移会涉及到整个集群, 那将是灾难性的。

    在一致性哈希算法下,会将新的redis节点计算出哈希值,放入哈希环中,这时,redis2H(key)<=7866的所有key值会进行转移,转移到redis4中;而当我们需要在新集群中删除掉其中一台redis2redis2中的所有key将会根据算法迁移到redis3上进行存储;


    一致性哈希算法在保持了单调性的同时,还是数据的迁移达到了最小,这样的算法对分布式集群来说是非常合适的,避免了大量数据迁移,减小了服务器的的压力;

     

    故障发现与故障转移

    Cluster集群在运行时所有的redis节点之间会通过ping/pong消息实现节点通信,消息不但传输节点槽信息,也能传播节点状态:主从状态,节点故障等。

    当集群中某一个节点出现问题时,集群会通过消息进行发现。与sentinel模式相同,节点故障在集群中也会经过主观下线、客观下线的过程,但是cluster集群中,并不需要sentinel来进行节点监控与故障转移,而是由集群中的master们来处理的。

  • 相关阅读:
    selenium+allure测试报告添加测试截图
    selenium pytest_html测试报告添加测试步骤截图
    pytest单元测试框架fixture应用
    unittest单元测试框架教程7-unittest.TestSuite类详解
    unittest单元测试框架教程6-unittest.TestCase类详解
    unittest单元测试框架教程5-使用subTest进行循环测试
    unittest单元测试框架教程3-利用unittest测试原理组织测试套件和用例
    unittest单元测试框架教程2-通过TestLoader运行用例
    Python学习相关链接
    GO语言相关的链接整理
  • 原文地址:https://www.cnblogs.com/HDMaxfun/p/15711892.html
Copyright © 2011-2022 走看看