目录

Redis持久化

RDB持久化

AOF持久化

Redis cluster

节点间内部通信原理

分布式寻址算法

Redis cluster主备切换原理

生产环境中redis部署

Redis rehash的过程


Redis如何才能做到高可用,如果系统有99%以上的时间都是可以对外提供服务的,那么就说系统是高可用的。Redis的高可用架构叫做failover故障转移也可以叫做主备切换。master node在故障时自动检测,并且将某个 slave node自动切换为master node的过程,叫做主备切换。这个过程实现了Redis的主从架构下的高可用。

Redis持久化

持久化主要是做灾难恢复、数据恢复,也可以归类到高可用的一个环节中去,Redis服务挂了然后就不可用了,重启Redis尽快让它对外提供服务,如果没做数据备份,这时候Redis启动了也不可用,数据都没了。大量的请求过来,缓存无法命中,在Redis里根本找不到数据,全落到数据库上了,承受不住就挂了,出现缓存雪崩问题。Redis持久化做好,备份和恢复方案做到企业级的程度,那么即使Redis故障了,也可以通过备份数据,快速恢复,一旦恢复立即对外提供服务。

通过RDB或AOF都可以将Redis内存中的数据给持久化到磁盘上面来,然后可以将这些数据备份到别的地方去,比如阿里云等云服务。如果Redis挂了,服务器上的内存和磁盘上的数据都丢了,可以从云服务上拷贝回来之前的数据,放到指定的目录中,然后重新启动Redis,Redis就会自动根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务。

如果同时使用RDB和AOF两种持久化机制,那么在Redis重启的时候,会使用AOF来重新构建数据,因为AOF中的数据更加完整。

RDB持久化

RDB持久化机制是对Redis中的数据执行周期性的持久化。RDB会生成多个数据文件,每个数据文件都代表了某一时刻Redis的数据,这种多个数据文件的方式,非常适合做冷备,可以将这种完整的数据文件发送到一些远程的安全存储上去,比如说Amazon的S3云服务上去,在国内可以是阿里云的ODPS分布式存储上,以定好的备份策略来定期备份Redis中的数据。RDB对Redis对外提供的读写服务,影响非常小,Redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可。相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复Redis进程,更加快速。如果想要在Redis故障时,尽可能少的丢失数据,RDB没有AOF好。一般来说RDB数据快照文件,都是每隔5分钟或者更长时间生成一次,这个时候就得接受一旦Redis进程宕机,那么会丢失最近5分钟(甚至更长时间)的数据。RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒甚至数秒。

AOF持久化

AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中,在Redis重启的时候,可以通过回放AOF日志中的写入指令来重新构建整个数据集。AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复。AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在rewrite log的时候,会对其中的指令进行压缩,创建出一份需要恢复数据的最小日志出来。在创建新日志文件的时候,老的日志文件还是照常写入。当新的merge后的日志文件 ready 的时候,再交换新老日志文件即可。AOF日志文件的命令通过可读较强的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据。对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大。AOF开启后支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,性能也还是很高的。(如果实时写入,那么QPS会大降,Redis性能会大大降低)

以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以类似AOF这种较为复杂的基于命令日志merge回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。

RDB和AOF选择

不要仅仅使用RDB,因为那样会导致你丢失很多数据。也不要仅仅使用AOF,因为那样有两个问题:第一,通过AOF做冷备,没有RDB做冷备来的恢复速度更快;第二,RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF 这种复杂的备份和恢复机制的bug。Redis支持同时开启开启两种持久化方式,可以综合使用 AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择;用RDB 来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复。

Redis cluster

自动将数据进行分片,每个master上放一部分数据,提供内置的高可用支持,部分master不可用时,还是可以继续工作的。在Redis cluster架构下,每个Redis要放开两个端口号,比如一个是6379,另外一个就是加1w的端口号,比如16379。16379端口号是用来进行节点间通信的,cluster bus的通信用来进行故障检测、配置更新、故障转移授权。cluster bus用了另外一种二进制的协议, gossip协议用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。

节点间内部通信原理

集群元数据的维护有两种方式集中式和Gossip协议。Redis cluster节点间采用gossip协议进行通信。

集中式是将集群元数据(节点信息、故障等等)集中存储在某个节点上。集中式元数据集中存储的一个典型代表,就是大数据领域的storm 。它是分布式的大数据实时计算引擎,是集中式的元数据存储的结构,底层基于 zookeeper(分布式协调的中间件)对所有元数据进行存储维护。Redis维护集群元数据采用另一个方式, gossip协议,所有节点都持有一份元数据,不同的节点如果出现了元数据的变更,就不断将元数据发送给其它的节点,让其它节点也进行元数据的变更。集中式的好处在于元数据的读取和更新,时效性非常好,一旦元数据出现了变更,就立即更新到集中式的存储中,其它节点读取的时候就可以感知到。不好在于所有的元数据的更新压力全部集中在一个地方,可能会导致元数据的存储有压力。gossip好处在于元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续打到所有节点上去更新降低了压力。不好在于元数据的更新有延时,可能导致集群中的一些操作会有一些滞后。

10000端口:每个节点都有一个专门用于节点间通信的端口,就是自己提供服务的端口号+10000,比如7001,那么用于节点间通信的就是17001端口。每个节点每隔一段时间都会往另外几个节点发送ping消息,同时其它几个节点接收到ping之后返回pong 。

交换的信息:信息包括故障信息,节点的增加和删除,hash slot信息等等。

gossip协议包含多种消息,包含ping , pong , meet , fail等等。

meet:某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其它节点进行通信。

Redis-trib.rb add-node

其实内部就是发送了一个gossip meet消息给新加入的节点,通知那个节点去加入我们的集群。

ping:每个节点都会频繁给其它节点发送 ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据。

pong:返回ping和meeet,包含自己的状态和其它信息,也用于信息广播和更新。

fail:某个节点判断另一个节点fail之后,就发送fail给其它节点,通知其它节点说,某个节点宕机啦。

ping时要携带一些元数据,如果很频繁,可能会加重网络负担。每个节点每秒会执行10次 ping,每次会选择5个最久没有通信的其它节点。当然如果发现某个节点通信延时达到了cluster_node_timeout / 2 ,那么立即发送 ping,避免数据交换延时过长,落后的时间太长了。比如两个节点之间都10分钟没有交换数据了,那么整个集群处于严重的元数据不一致的情况,就会有问题。所以cluster_node_timeout可以调节,如果调得比较大,那么会降低ping的频率。每次ping,会带上自己节点的信息,还有就是带上1/10其它节点的信息,发送出去,进行交换。至少包含3个其它节点的信息,最多包含 总节点数减2个其它节点的信息。

分布式寻址算法

hash算法(大量缓存重建)

一致性hash算法(自动缓存迁移)+ 虚拟节点(自动负载均衡)

Redis cluster的hash slot算法

hash算法

根据key值计算hash值,然后对节点数取模。然后打在不同的master节点上。一旦某一个 master节点宕机,所有请求过来,都会基于最新的剩余master节点数去取模,尝试去取数据。这会导致大部分的请求过来,全部无法拿到有效的缓存,导致大量的流量涌入数据库。

一致性hash算法

一致性hash算法将整个hash值空间组织成一个虚拟的圆环,整个空间按顺时针方向组织,下一步将各个master节点(使用服务器的ip或主机名)进行hash。这样就能确定每个节点在其哈希环上的位置。来了一个key,首先计算hash值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,遇到的第一个 master 节点就是 key 所在位置。在一致性哈希算法中,如果一个节点挂了,受影响的数据仅仅是此节点到环空间前一个节点(沿着逆时针方向行走遇到的第一个节点)之间的数据,其它不受影响。增加一个节点也同理。一致性哈希算法在节点太少时,容易因为节点分布不均匀而造成缓存热点的问题。为了解决这种热点问题,一致性hash算法引入了虚拟节点机制,即对每一个节点计算多个hash,每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布,负载均衡。

Redis cluster的hash slot算法

Redis cluster有固定的16384个hash slot,对每个key计算CRC16值,然后对16384取模,可以获取key对应的hash slot。Redis cluster中每个master都会持有部分 slot,比如有3个master,那么可能每个 master持有5000多个hash slot。hash slot让 node的增加和移除很简单,增加一个 master,就将其他master的hash slot移动部分过去,减少一个master,就将它的hash slot移动到其他master上去。移动hash slot的成本是非常低的。客户端的 api,可以对指定的数据,让他们走同一个hash slot,通过hash tag来实现。任何一台机器宕机,另外两个节点不影响的。因为key找的是hash slot,不是机器。

Redis cluster主备切换原理

Redis cluster的高可用的原理,几乎跟哨兵是类似的。判断节点宕机,如果一个节点认为另外一个节点宕机,那么就是pfail ,主观宕机。如果多个节点都认为另外一个节点宕机了,那么就是fail ,客观宕机,跟哨兵的原理几乎一样,sdown,odown。在cluster-node-timeout内,某个节点一直没有返回pong ,那么就被认为pfail 。如果一个节点认为某个节点pfail了,那么会在gossip ping消息中, ping给其他节点,如果超过半数的节点都认为pfail了,那么就会变成fail 。对宕机的master node,从其所有的slave node中,选择一个切换成master node。检查每个slave node与master node断开连接的时间,如果超过了cluster-node-timeout * cluster-slave-validity-factor ,那么就没有资格切换成master 。

从节点选举

每个从节点,都根据自己对master复制数据的 offset,来设置一个选举时间,offset越大(复制数据越多)的从节点,选举时间越靠前,优先进行选举。所有的master node开始slave选举投票,给要进行选举的slave进行投票,如果大部分master node (N/2 + 1) 都投票给了某个从节点,那么选举通过,那个从节点可以切换成master。从节点执行主备切换,从节点切换为主节点。

与哨兵比较

整个流程跟哨兵相比,非常类似,所以说,Redis cluster 功能强大,直接集成了 replication 和 sentinel 的功能。

生产环境中redis部署

Redis cluster10台机器,5台机器部署了Redis 主实例,另外5台机器部署了Redis的从实例,每个主实例挂了一个从实例,5个节点对外提供读写服务,每个节点的读写高峰QPS可能可以达到每秒5万,5台机器最多是25万读写请求每秒。

机器配置

32G内存+ 8核CPU + 1T磁盘,分配给Redis进程的是10g内存,线上生产环境Redis的内存尽量不要超过10g,超过10g可能会有问题。5台机器对外提供读写,一共有50g内存。每个主实例都挂了一个从实例,所以是高可用的,任何一个主实例宕机,都会自动故障迁移,Redis 从实例会自动变成主实例继续提供读写服务。

往内存里写的数据?每条数据的大小?商品数据,每条数据是10kb。100条数据是1mb,10 万条数据是1g。常驻内存的是200万条商品数据,占用内存是20g,仅仅不到总内存的 50%。目前高峰期每秒就是3500左右的请求量。大型的公司,会有基础架构的team负责缓存集群的运维。

Redis rehash的过程

Redis主要用于存储键值对(Key-Value Pair),而键值对的存储方式是由字典实现,而Redis中字典的底层又是通过哈希表来实现的。通过哈希表中的节点保存字典中的键值对。类似Java中的HashMap,将Key通过哈希函数映射到哈希表节点位置。Redis中字典的数据结构如下:

// 字典对应的数据结构,有关hash表的结构可以参考redis源码,再次就不进行描述
typedef struct dict {dictType *type;  // 字典类型void *privdata;  // 私有数据dictht ht[2];    // 2个哈希表,这也是进行rehash的重要数据结构,从这也看出字典的底层通过哈希表进行实现。long rehashidx;   // rehash过程的重要标志,值为-1表示rehash未进行int iterators;   //  当前正在迭代的迭代器数
} dict;

在对哈希表进行扩展或者收缩操作时,程序需要将现有哈希表包含的所有键值对rehash到新哈希表里面,具体过程如下:

为字典的备用哈希表分配空间

如果执行的是扩展操作,那么备用哈希表的大小为第一个大于等于需要扩容的哈希表的键值对数量*2 的 2"(2 的 n 次方幂);【5*2=10,所以备用哈希表的容量为第一个大于 10 的 2",即 16】。如果执行的是收缩操作,那么备用哈希表的大小为第一个大于等于需要扩容的哈希表的键值对数量(ht[0] .used)的 2"。

渐进式rehash

rehash过程在数据量非常大(几千万、亿)的情况下并不是一次性地完成的,而是渐进式地完成的。渐进式rehash的好处在于避免对服务器造成影响。

渐进式rehash的本质:

借助rehashidx,将rehash键值对所需的计算工作均摊到对字典的每个添加、删除、查找和更新操作上,从而避免了集中式rehash而带来的庞大计算量。

在rehash进行期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定的操作以外,还会顺带将原哈希表在 rehashidx索引上的所有键值对rehash到备用哈希表,当rehash工作完成之后,程序将 rehashidx属性的值加1。

Redis高可用架构相关推荐

  1. 教你用 3 台机器搞定一个 Redis 高可用架构

    转载自   教你用 3 台机器搞定一个 Redis 高可用架构 基于内存的 Redis 应该是目前各种 Web 开发业务中最为常用的 key-value 数据库了. 我们经常在业务中用其存储用户登陆态 ...

  2. 带哨兵节点的链_深入学习Redis高可用架构:哨兵原理及实践

    原标题:深入学习Redis高可用架构:哨兵原理及实践 " 在上篇文章<深入学习 Redis 高可用的基石:主从复制>中曾提到,Redis 主从复制的作用有数据热备.负载均衡.故障 ...

  3. 深入学习Redis高可用架构:哨兵原理及实践

    Redis 主从复制的作用有数据热备.负载均衡.故障恢复等:但主从复制存在的一个问题是故障恢复无法自动化. 本文将要介绍的哨兵,它基于 Redis 主从复制,主要作用便是解决主节点故障恢复的自动化问题 ...

  4. Redis高可用架构 (redis主从+sentinel)

    cat >> /etc/sysctl.conf< cat >>/etc/security/limits.conf<<EOF soft nproc 65535 ...

  5. Redis高可用架构-Redis集群,一文get三种方式

    前言 容量不够,redis如何进行扩容? 并发写操作, redis如何分摊? 另外,主从模式,薪火相传模式,主机宕机,导致ip地址发生变化,应用程序中配置需要修改对应的主机地址.端口等信息. 之前通过 ...

  6. 【Redis】高可用架构之Cluster集群和分⽚

    高可用架构之Cluster集群和分⽚ 1. 前言 2. Cluster 模式介绍 2.1 什么是Cluster模式? 2.2 为什么需要Cluster模式? 2.2.1 垂直拓展(scale up)和 ...

  7. 携程数据库高可用架构实践

    作者:携程技术团队,来自:DataFunTalk 导读: 我们推荐使用数据库三副本,一主一从一异地容灾.如果想要节省成本,也可以只保留两副本,但是一旦其中一台服务器发生故障,服务器维修时间会比较长,那 ...

  8. Redis 高可用篇:你管这叫主从架构数据同步原理?

    高可用有两个含义:一是数据尽量不丢失,二是服务尽可能提供服务. AOF 和 RDB 保证了数据持久化尽量不丢失,而主从复制就是增加副本,一份数据保存到多个实例上.即使有一个实例宕机,其他实例依然可以提 ...

  9. 数据库高可用架构(MySQL、Oracle、MongoDB、Redis)

    一.MySQL MySQL小型高可用架构 方案:MySQL双主.主从 + Keepalived主从自动切换 服务器资源:两台PC Server 优点:架构简单,节省资源 缺点:无法线性扩展,主从失败之 ...

最新文章

  1. Android 使用java 代码获取res 里面的value 定义的数组
  2. 本科4篇顶会!清华特奖高天宇干货分享:我是这样写论文、做实验、与导师相处...
  3. 车辆2D/3D--Deep MANTA: A Coarse-to-fine Many-Task Network for joint 2D and 3D vehicle analysis
  4. Groovy—沉睡的雄狮
  5. java web文件夹_JAVA WEB项目文件夹上传下载解决方案
  6. OS / 进程启动过程
  7. 部署docker-consul群集,Harbor构建Docker私有仓库
  8. 江苏自考计算机组成原理多少分及格,自考《计算机组成原理》基本概念第七章...
  9. idea mac 替换_史上最全的IntelliJ IDEA For Mac快捷键!快来收藏吧!
  10. mongodb定时删除数据(索引删除)
  11. python爬取今日头条新闻,js解密
  12. 注意!SQLite被曝漏洞,Chrome 火狐等数千应用或受影响
  13. IDEA主题设置,自定义主题
  14. 可以直接复制的emoji符号(表情)
  15. L2-1 特立独行的幸福 (25分)
  16. Friendship 友谊--我最宝贵的财富
  17. C#操作TMPOS58串口打印机一些心得
  18. keil下汇编语言调试分析
  19. 稠密的无人机激光雷达点云数据处理与分析方法与工具科普系列(一)
  20. 内嵌式js微信扫码登录及自定义样式

热门文章

  1. 为什么国外服务器域名备案可以不进行?
  2. NAT网关(SNAT,DNAT)
  3. Android幸运大转盘
  4. 零基础如何学习 Web 安全?
  5. 洛朗级数与泰勒展开的区别
  6. 我不需要保险,全家都不需要
  7. Axure 元件库-原型
  8. 【 FPGA 】超声波测距小实验(四):数码管显示测距结果
  9. 用python抢火车票
  10. 70. Climbing Stairs. Iter--Sol