• 3------集群篇


    主从同步

    当主节点(Master)挂掉的时候,运维让从节点(slave)过来接管,服务就可以继续,否则主节点需要经过数据恢复和重启的过程。

    CAP原理

    分布式存储的理论基石

    1. C:Consistent,一致性
    2. A:Availability,可用性
    3. P:Partition tolerance,分区容忍性

    分布式系统的节点往往都是分布在不同的机器上进行网络隔离的,网络分区。

    网络分区:两个节点之间不能通信

    网络分区发生时,一致性和可用性两难全

    最终一致

    Redis的主从数据是异步同步的,所以分布式系统并不满足一致性,但是满足可用性

    但是满足最终一致性,因为网络恢复后,从节点会采用各种策略努力追赶恢复的。

    Redis同步支持主从同步和从从同步

    增量同步

    主节点将修改主节点状态的指令   写入  下图环状的buffer数组当中,循环一直覆盖写。

    从节点一直从上面读指令,达到和主节点一致的状态、、、并且返回自己复制到哪儿了

    但是遇到网络问题,那么指令就会被覆盖掉

    这个时候就需要快照同步。

    快照同步

    在主节点上来一次bgsave,将当前内存的数据全部快照到磁盘文件中

    然后,再将快照文件发送给从节点。从节点来一个全量加载

    加载之前先要将当前内存的数据清空,加载完毕后通知主节点继续进行增量同步

    但是!!!!这个时候,主节点的buffer还是在一直复制的,如果快照时间过长或者buffer的太小,那么就会造成快照死循环。

    增加从节点

    当从节点刚刚加到集群中,必须来一次快照同步,才能进行增量同步

    无盘复制

    主要指快照同步

    主节点直接通过套接字将快照内容发送到从节点

    主节点会一边遍历内存,一边将序列化的内容发送到从节点,从节点将收到的内容加载到磁盘,最后再进行一次加载。

    wait指令

    Redis的复制是异步的,wait指令可以让异步复制变身同步复制,确保系统的强一致性

    set key value
    wait 1 0

    两个参数:第一个参数从节点的数量;第二个参数是时间t。

    等待wait指令之前的所有写操作同步到N个从节点,最多等待时间t,等待从节点同步。如果t=0,表示无限等待直到N个从节点同步完成。

    假设此时出现了网络分区,wait指令第二个参数为0,那么redis服务器就失去了可用性

    Sentinel

     哨兵系统,主节点坏了,自动将从节点升级为主节点,不用手动

    Sentinel负责持续监控主从节点的健康,当主节点挂了,自动选择一个最优的从节点切换为主节点。

    客户端连接集群,会首先连接Sentinel,通过Sentinel来查询主节点的地址,然后再连接主节点进行数据交互。

    当主节点故障了,客户端会重新想Senatinel要地址,Sentinel会将最新的主节点告诉客户端。

    当主节点恢复之后,自动称为从节点。

    消息丢失

    Sentinel无法保证数据不丢失,但是尽量保证信息少丢失

    限制主从延迟不要太大

    # 保证至少一个从节点正常复制
    min-slave-to-write 1
    
    #什么是正常复制,那就是每过10s收到从节点的反馈
    min-slaves-max-lag 10

    Sentinel基本用法

    客户端通过Sentinel来发现从节点的地址,然后再通过地址建立相应的连接。

    Sentinel默认端口为26379

    客户端如何知道地址发生改变?

    ------建立连接的时候进行主节点地址变更判断

    连接池建立新连接时,会去查询主节点地址,然后跟内存中的主节点地址进行比对,如果变更了,就断开所有连接,重新使用新地址进行连接。如果旧的主节点挂掉了,那么所有正在使用的连接都会关闭,然后在重连时就会用上新地址

    Codis分而治之

    单个Redis内存不宜过大,内存太大导致rdb文件过大,进一步导致主从同步时全量同步时间过长,在实例重启恢复时也会消耗很长的数据加载时间。

    Codis:将众多小内存的Redis实例整合起来,将分布在多台机器上的众多CPU核心的计算能力聚集在一起,完成海量数据存储和高并发读写操作

    当客户端向Codis发送指令时,Codis负责将指令转发到后面的Redis实例来致性,并且将结果返回给客户端。

    Codis是一个转发代理中间件,可以启动多个Codis实例,供客户端使用,每个Codis节点都是对等的。

    还可以起到容灾功能

    Codis分片原理

    Codis负责将特定的key转发到特定的Redis实例中

    Codis默认将所有的key划分为1024个槽位,将key进行hash,然后得到槽位。然后到相应的redis实例当中查询

    不同的Codis实例之间槽位关系如何同步?

    利用zookeeper,存储Codis实例和槽位之间的通信,多个Codis之间同步。

    扩容

    Codis本来只有一个Redis实例,接下来新加了一个,那么就会将一半的槽位分给新的节点。

    利用SLOTSSCAN指令扫描一个槽下的所有key,然后挨个迁移。

    迁移的时候,Codis的槽有可能还在接收新的key-----------------------那么,COdis接收到位于正在迁移槽位中的key后,会立即强制对当前的单个key进行迁移,迁移完成后,再将请求转发到新的Redis实例中

    自动均衡

    Codis会查看每个Redis对应的槽位,然后自动均衡负载

    Codis的代价

    1. 不支持事务
    2. 迁移会变得困难
    3. 网络开销变大,毕竟多走了一个网络节点

    Codis的优点

    简单

    mget指令的操作过程

    架构变迁

    毕竟不是官方的,老是随着官方的redis改变

    Codis尴尬

    不是亲生的

    Codis后台管理

    一个很友好的后台web界面

    Cluster

    redis Cluster去中心化的集群方案

    集群由三个Redis节点组成,每个节点负责整个集群的一部分数据,每个节点负责的数据多少可能不一样。二进制协议通信

    将数据划分为16384个槽位,每个节点负责其中一部分槽位。

    客户端来连接集群,会得到一份集群的槽位配置信息,然后通过这个配置信息去查询完事了。

    客户端需要缓存槽位的信息,可能客户端和服务器存储槽位的信息不一致的情况,这个时候还需要校准。

    Redis Cluster的每个节点会将集群的配置信息持久化到配置文件中,所以必须保证配置文件时可写的,而且尽量不要依靠人工修改配置文件

    槽位定位方法

    将key进行hash,然后将哈希值与槽位进行哈希

    Redis Cluster允许将用户强制把某个key挂在特定的槽位上

    跳转

    当节点发现客户端的请求中的槽位并不归属自己管,就会给客户端发送一个带跳转地址的信息,让客户端去连接这个节点获取数据

    迁移

    从源节点获取内容---存区目标节点------从源节点中删除

    整个转移过程中,转移是一步一步的,假如单个key过大,那会引起卡顿的。

    客户端首先会访问旧节点,找到了还好,找不到旧节点会重定向;----客户端向新节点询问下Asking,然后再致性原先的操作指令。Asking指令避免重定向循环。

    容错

    每个节点设置几个从节点,当主节点发生故障时,集群就会自动升级从节点;同时允许若干个主节点发生故障

    网络抖动

    有时候,有些节点突然失联,突然又连接上了,Redis Cluster给一个失联的时间,超过这个时间就表示失联了;主从切换。

    cluster-node-timeout

    可能下线和确定下线

    Redis cluster是去中心化的,一个节点认为某个节点失联了,并不管用,只有大多数节点都认定某个节点失联了,集群才认识该节点需要进行主从切换来容错。

    比如:某个节点发现某个节点失联了(PFail),它会将这条信息向整个集群广播,其它节点就可以收到这点的失恋信息。如果收到了某个节点失联的数量已经达到了集群的大多数,就可以标记这个节点失联。Fail

    Cluster基本用法

    导入redis-py-cluster模块才可以使用

    cluster不支持事务:Cluster的mget方法比redis要慢很多,被拆分成了多个get指令;Cluster的rename方法不再是原子的,它需要将数据从源节点转移到目标节点。

    槽位迁移感知

    客户端保存了槽位和节点的映射关系表,它需要及时得到更新。

    moved指令:客户端请求了错误的节点,节点指挥客户端重定向到正确的节点上。并且刷新客户端的配置信息

    asking指令:再迁移时发送的指令。

    不过上述的两个指令都是重试指令,需要限制重试的次数。高于这个次数就报错

    集群变更感知

    当服务节点变更时,客户端应该立即得到通知以实时刷新自己的节点关系表。那么客户端是如何知道的

    1. 目标节点挂掉了,客户端抛出ConnectionError指令,紧接着随机挑一个节点来重试,然后提供moved指令进行重试
    2. 运维手动修改集群信息,将主节点切换到其它节点,并将旧的主节点移除出集群,这时打在旧节点上的指令会受到ClusterDown错误,然后客户端关闭所有的连接,清空槽位映射关系表,重新尝试初始化节点信息
  • 相关阅读:
    UWP 2018 新版 NavigationView 尝鲜
    UWP 五星评价(不跳转到龟速商店)
    UWP 查找模板中的控件
    Win10版本号区分
    基于Windows 机器学习(Machine Learning)的图像分类(Image classification)实现
    海瑞菌的web前端学习直播间
    【javascript】对原型对象、原型链的理解
    公众号【海瑞菌】的近期总结
    我的2018年【年末总结】--2019年初计划
    【js操作url参数】获取指定url参数值、取指定url参数并转为json对象
  • 原文地址:https://www.cnblogs.com/sicheng-li/p/13298710.html
Copyright © 2020-2023  润新知