深入浅出百亿请求高可用Redis(codis)分布式集群揭秘

  • 时间:
  • 浏览:40
  • 来源:小天博客 - 专注共享小乖博客资源

摘要:作为noSql中的kv数据库的王者,redis以其高性能,低传输速率,丰厚的数据形态备受开发者青睐,只是我机会redis在水平伸缩性上受限,如何做到都都还可以 水平扩容,一起去对业务无侵入性是你你这些使用redis的开发人员回会面临的问题图片,而redis分布式避免方案的一一六个开源产品【codis】较好的弥补了你你这些弱势,本文主要讲解codis是如何做到对业务无感知,平滑迁移,迁移性能高,迁移异常避免,高可用以及常见的redis的避坑指南,真是codis目前随着公司的nosql产品越来越成熟图片 是什么期图片 的得话,生命周期也即将开始英语 英语 ,不过鉴于还有你你这些同学对codis的原理比较感兴趣,于是将后后的分享的内容重新分发,当然codis在公司外应用目前依旧还是相对比较广泛。

目录

一、背景

二、Redis相关基础概览

2.1Redis简介

2.2Redis的特点

2.3Redis应用场景

三、Redis分布式避免方案公司内外比较

四、Codis的分发

4.1 Codis整体的分发

4.2Codisproxy的分发实现

五、数据可靠性 &高可用&容灾&故障转移&脑裂避免

5.1 数据可靠性

5.2 高可用&容灾&故障转移

六、codis水平扩容细节&迁移异常避免

6.1 Codis扩容迁移细节

6.2 迁移异常避免

七、Codis相关数据

八、运维手册及避坑指南

九、参考资料

一、背景

随着直播元年开启,不多的直播产品如春笋般再次出现,在拉动营收的过程中,产品竭尽全力思考着各种活动来刺激用户的消费欲望,而这类 活动的基础形式只是我榜单,在2016年让.我都 基于cmem及扫描流水表的辦法 来实现榜单排名,2017开始英语 英语 ,让.我都 对原有系统进行重构,使用redis作为让.我都 的榜单基础存储,在重构的过程中接到调研redis分布式避免方案的任务后后,比对业内各种开源产品,最后定下Codis,并对其中细节做了你你这些研究,期间在与Codis作者交流的过程中,有幸知道增值产品部的simotang机会在部门引入codis近2年时间,遂加入到codis的运维工作中,目前在部门內部署运维codis集群15套,2T容量,总日访问量百亿+.支撑了互动视频产品部基础存储,运营活动,榜单类业务2年多,共计50多个活动,榜单上千个。一起去在这里非常感谢codis作者spinlock在接入codis过程中给予的指导与帮助。见spinlock github 与 codis地址

二、Redis相关基础概览

2.1 Redis简介

redis是一一六个基于内存一起去具备数据持久化能力的高性能,低传输速率的KV数据库,value的数据形态都时只是我string,hash表,list(列表),set(集合),sortedset(有序集合)。

Redis(RemoteDictionary Server)

Redis is anopen source (BSD licensed), in-memory data structure store, used as adatabase, cache and message broker. It supports data structures suchas strings, hashes, lists, sets, sorted sets with rangequeries,Practice: http://try.redis.io/



2.2 Redis的特点

1. 单线程池池异步架构(单线程池池,收包,发包,解析,执行,多路io复用接收文件事件)

2. k-v形态,value支持丰厚的数据形态(string,hash,list,set,sortset)

3. 高性能,低传输速率,基于内存操作,Get/Set10w+,高性能,基于RDB、AOF落地保证数据可靠性

4. 丰厚的形态,可用于缓存,消息队列,TTL过期

5. 支持事务,操作是原子性,要么删剪提交,要么删剪不提交。

2.3 Redis应用场景

string 计数器,用户信息(id)映射,唯一性(这类 用户资格判断),bitmap
hash 常见场景:存储对象的属性信息(用户资料)
list 常见场景:评论存储,消息队列
set 常见场景:资格判断(这类 用户奖励领取判断),数据去重等
sorted set 常见场景:排行榜,延时队列
你你这些 分布式锁设计  推荐2篇文章:

基于Redis的分布式锁到底安全吗(上)

http://zhangtielei.com/posts/blog-redlock-reasoning.html

基于Redis的分布式锁到底安全吗(下)

http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html

2.4 写在前面:codis与redis的关系

codis与redis之间关系只是我codis是基于多个redis实例做了一层路由层来进行数据的路由,每个redis实例承担一定的数据分片

2.5 redis学习资料

机会本文重点在于redis分布式避免方案,对于redis相关的基础每段,让.我都 都时要参考两本书及相关源码分析文章

1. Redis开发与运维(付磊)

2. Redis设计与实践(黄健宏)(值得多看两遍)

三、Redis分布式避免方案公司内外比较

在比较方案后后,让.我都 先根据让.我都 的经验输出了让.我都 期望的避免方案应该具备的能力,以此来衡量让.我都 的挑选标准

基于此让.我都 对公司内外做了一一六个如下的比较

【公司内组件对比】

【公司外组件对比】

基于以上比较,codis作为开源产品,都时要很直观的展示出codis运维成本低,扩容平滑最核心的优势.

对于数据安全目前让.我都 基于机器本机48小时滚动备份加带公司刘备备份(每天定时目录备份的系统)的兜底备份,对于监控,目前接入monitor单机备份和米格监控告警)

四、codis的分发

4.1Codis整体的分发

codis官网

【图codis架构图】

如上图所示,codis整体属于二层架构,proxy+存储,相对于ckv+无proxy的设计来说整体设计会相对简单,一起去对于客户端连接数据逐渐增大的状况下,只是我用去做数据层的副本扩容,而只时要做proxy层的扩容,从这你你这些上看,成本会低你你这些,只是我对于连接数不大的状况下,还时要单独去部署proxy,从这你你这些上看,成本会高你你这些。

其中,开源的codisproxy的服务的注册发现是通过zk来实现,目前部门是基于l5来做.

从整体的分发图来看,codis整体的架构比较清晰,其中codisproxy是分布式避免方案设计中最核心的每段,存储路由,分片迁移均与codisproxy分不开,这块让.我都 来看一下codisproxy的设计实现。

4.2Codisproxy的分发实现

codisproxy的架构实现分成一一六个每段,分别为4.2.1的路由映射的细节与4.2.2的proxy请求避免的细节

4.2.1 路由映射细节

如下图所示:该每段主要涉及到codis的路由细节,主要涉及到如何将一一六个key映射到具体的物理结点

【图】路由映射细节



如上图所示:该每段主要涉及到codis的路由细节

| 相关词汇说明

slot:分片信息,在redis当中仅仅表示一一六个数字,代表分片索引。每个分片会归属于具体的redis实例

group:主只是我虚拟结点,由多台redis机器组成,形成一主多从的模式,是逻辑意义上的结点

为了帮助让.我都 对proxy路由映射的细节一一六个更深入的理解,我分发了好多个常见的路由映射的相关问题图片来帮忙让.我都 理解

问题图片一:proxy是如何把请求映射到具体的redis实例中?

Codis基于crc32的算法%1024得到对应的slot,slot只是我所谓的逻辑分片,一起去codis会将对应的逻辑分片映射到对应的虚拟结点上,每个虚拟结点是由1主多从的物理redis结点组成。至于缘何会用crc32,你你这些具体也越来越细究,作者也是借鉴于rediscluster中的实现引入的。通过引入逻辑存储结点group,原本即使底层的主机机器实例变更,只是我映射上层的映射数据,对上层映射透明,便于分片的管理。

问题图片二,proxy是如何做到读写分离

如上图所示,key映射到具体的虚拟结点时,都都还可以 感知到虚拟结点对应的主与备机实例,此时redisproxy层面都都还可以 识别到具体的redis命令得到对应的命令是读与写,再根据集群的配置不是支持读写分离的形态,如配置的是支持,则随机路由到主与从机实例,如配置的是不支持,则路由到主机补全

问题图片三,proxy目前支持那些命令,不是支持批量命令,如何保证原子性

命令支持链接

命令支持每段:Prxoy支持的命令分为你这些:不支持命令,半支持命令,支持命令,除了上表所示命令外,你你这些命令proxy均是支持的,其中不支持命令每段主只是我机会那些命令参数中越来越key,只是我无法识别路由信息,我只是我知道具体路由到哪台实例上,而半支持命令每段通常是会操作多个key,codis基于你这些简单实现,以第一一六个key的路由为准,只是我时要业务方被委托人来保持多个key路由到同一一六个slot,当然业务也是都时要不保证,具体后果业务来承担,是你这些弱校验的模式,而公司级产品ckv+对于多key操作是强校验,机会多key没了同一slot上,则以错误的形式返回。

多key操作&原子性每段:Redis你这些对于多key的你你这些操作这类 mset等命令是原子性的,而在分布式操作下,多key会分布到多个redis实例当中,涉及到分布式事务,你你这些在codis当中进行了复杂化避免,多key操作拆成多个单key命令操作,你你这些codis当中的mset多key操作不具备原子性的语义。

  问题图片四,如何保证多个key在一一六个slot当中

你你这些场景下,让.我都 希望使用到lua机会你你这些半支持命令来保证让.我都 操作的原子性,只是我让.我都 时要在业务层面来去保证多key在一一六个slot当中,codis采用了和rediscluster一样的模式,基于hashtag,这类 要我让七天的主播榜单都中路由在同一一六个slot得话,{anchor_rank}day1,{anchor_rank}day2,{anchor_rank}day3,即可支持,对只是我采用大括号的模式,codis会识别大括号,只会取大括号中的字符串进行hash操作。

4.2.2Proxy请求避免细节

如下图所示:该每段主要涉及到proxy的避免细节,涉及到如何接受一一六个请求到响应回包的过程

【图】Proxy请求避免细节

如上图所示:该每段主要涉及到proxy的避免细节

Codisproxy主要基于go语言你你这些从语言层面天然支持协程的语言来实现的

1)proxy接收客户端的连接后后,新建一一六个session,一起去启动session中reader与writer一一六个协程,reader主要用于接收客户端请求数据并解析,对多key的场景下进行命令的拆分,只是我将请求通过router进行分发到具体的redis实例,并将redis避免的数据结果写到通道到中,writer从通道中接收对应的结果,将写回给客户端。

2)Router层主只是我通过crc命令得到key对应的路由信息,从源码都时要想看 hashtag的形态,codis真是也是支持的。

hash源码
至此,proxy相关的路由映射与请求避免细节机会开始英语 英语 ,整体下来是时要很简单
五、数据可靠性&高可用&容灾&故障转移&脑裂避免

作为存储层,数据可靠性与服务高可用是稳定性的核心指标,直接影响到上层核心服务的稳定性,本节将主要针对你你这些六个指标来做一下阐述。

5.1 数据可靠性

作为codis的实现来讲,数据高可靠主只是我redis你这些的能力,通常存储层的数据高可靠,主只是我单机数据高可靠+远程数据热备+定期冷备归档实现的

单机数据高可靠主只是我借利于redis你这些的持久化能力,rdb模式(定期dum)与aof模式(流水日志),这块都时要参考前文所示的2本书来了解,其中aof模式的安全性更高,目前让.我都 线上也是将aof开关打开,在文末也会删剪描述一下。

远程数据热备主只是我借利于redis自身具备主从同步的形态,全量同步与增量同步的实现,让redis具体远程热备的能力

定期冷备归档机会存储服务在运行的过程中机会地处人员误操作数据,机房网络故障,硬件问题图片是因为分析数据丢失,只是我让.我都 时要你你这些兜底方案,目前主只是我单机滚动备份备份最近48小时的数据以及sng的刘备系统来做冷备,以备非预期问题图片是因为分析数据丢失,都都还可以 快速恢复。

5.2 高可用&容灾&故障转移

codis的架构你这些分成proxy集群+redis集群,proxy集群的高可用,都时要基于zk机会l5来做故障转移,而redis集群的高可用是借利于redis开源的哨兵集群来实现,那边codis作为非redis组件,时要避免的一一六个问题图片只是我如何集成redis哨兵集群。本节将该问题图片分成三每段,介绍redis哨兵集群如何保证redis高可用,codisproxy如何感知redis哨兵集群的故障转移动作,redis集群如何降低“脑裂”的地处概率。

5.2.1 哨兵集群如何保证redis高可用

Sentinel(哨岗,哨兵)是Redis的高可用避免方案:由一一六个或多个Sentinel实例组成的Sentinel系统,都时要监视任意多个主服务器,以及那些主服务器属下的所有的从服务器,并在被监视的主服务器进入下线状况时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,只是我由主服务器代替已下线的主服务器继续避免命令请求。

通常来说要达到服务的高可用的效果时要做一一六个事情:故障探测与故障转移(即选主并做主从切换)

故障

探测

Sentinel集群故障转移

1)选出一台Sentinel-leader,来进行故障转移操作(raft协议,过半选举)

if (winner && (max_votes < voters_quorum || max_votes < master->quorum))

2)领头sentinel在已下线的从服务器底下,挑选一一六个从服务器,并将其转换为主服务器

3)让已下线主服务器属下的所有从服务器改为克隆qq好友好友新的主服务器

4)将已下线主服务器设置为新的主服务器的从服务器,当你你这些旧的主服务器重新上线时,它就会成为新的主服务器的从服务器

注:从服务器中挑选新的主服务器的步骤

1)选举列表中剔除所有下线机会断线状况的从服务器

剔除所有最近五秒内越来越回复过领头Sentinel的info命令的从服务器

剔除所有与已下线服务器超过down-after-millisenconds * 10(ms)的从服务器

2)根据从服务器优先级(取最高),克隆qq好友好友偏移量(取最大),运行ID(取最小)1)每1秒,向主服务器,从服务器,你你这些sentinel实例发送ping命令

有效回复:+PONG, -Loading,+MASTERDOWN你这些回复你这些

无效回复:除以上你这些回复之外的回复,机会在指定时限内越来越返回的回复

Sentinel.conf -> Sentinel down-master-millsenconds master 5000

(当连续50秒,sentinel都接收到无效请求机会无回复时,就会将master标记为主观下线)

2)主观下线后后,向你你这些sentinel发送询问命令,机会达到配置中指定的数量时,则标记master为客观下线

Sentinel monitor master xx.xx.xx.xx 2

故障

转移

Sentinel集群故障转移

1)选出一台Sentinel-leader,来进行故障转移操作(raft协议,过半选举)

if (winner && (max_votes < voters_quorum || max_votes < master->quorum))

2)领头sentinel在已下线的从服务器底下,挑选一一六个从服务器,并将其转换为主服务器

3)让已下线主服务器属下的所有从服务器改为克隆qq好友好友新的主服务器

4)将已下线主服务器设置为新的主服务器的从服务器,当你你这些旧的主服务器重新上线时,它就会成为新的主服务器的从服务器

注:从服务器中挑选新的主服务器的步骤

1)选举列表中剔除所有下线机会断线状况的从服务器

剔除所有最近五秒内越来越回复过领头Sentinel的info命令的从服务器

剔除所有与已下线服务器超过down-after-millisenconds * 10(ms)的从服务器

2)根据从服务器优先级(取最高),克隆qq好友好友偏移量(取最大),运行ID(取最小)

5.2.2 codis如何感知哨兵集群的故障转移动作

codis的架构你这些分成proxy集群+redis集群,redis集群的高可用是由哨兵集群来保证的,越来越proxy是如何感知redis主机故障,只是我切换新主保证服务高可用的呢?

如上图所示,proxy你这些会监听sentinle集群的+switch-master事件,该事件发出,是因为分析redis集群主机再次出现问题图片,sentinel集群开始英语 英语 进行选举并切换主机,proxy监听了sentinel的主从切换事件,收到主从切换事件后后,proxy会做一一六个动作,只是我把所有sentinel上的集群所感知的当前认为的主机拉取出来,挑选过半sentinel认为的主机当作目前的集群主机。

讲到这里,让.我都 机会会忽略一一六个问题图片,只是我配置存储,配置中心的存储还是旧的主机,一旦proxy重起,那拉取的依旧是故障的主机,真是dashboard和proxy也做了一样的事情,收到主从切换事件后后,就会将新主持久化到storage中(目前为zk)

5.2.3 脑裂避免

脑裂(split-brain)集群的脑裂通常是地处在集群中每段节点之间不可达而引起的。如下述状况地处时,不同分裂的小集群会自主的挑选出master节点,造成原本的集群会一起去地处多个master节点。,结果会是因为分析系统混乱,数据损坏。

在你你这些问题图片上,这里simotang同学机会讲解的非常完善了,大规模codis集群的治理与实践,这里简单说一下,机会redis集群必须单纯的依赖过半选举的模式,机会redismaster自身越来越做检测自身健康状况而降级的动作,你你这些让.我都 时要你这些master健康状况辅助判断降级的辦法 。具体实现为

1)降级双主再次出现的概率,让Quorums判断更加严格,让主机下线判断时间更加严格,让.我都 部署了5台sentinel机器覆盖各大运营商IDC,必须4台主观认为主机下线的后后才做下线。

2)被隔离的master降级,基于共享资源判断的辦法 ,redis服务器上agent会定时持续检测zk不是通常,若连接不上,则向redis发送降级指令,不可读写,牺牲可用性,保证一致性。

六、codis水平扩容细节&迁移异常避免

机会codis是针对redis分布式的避免方案,必然会面临着redis单点容量不足英文的状况下水平扩容的问题图片,本节主要针对codis水平扩容与迁移异常的细节做一下说明,让.我都 先带着一一六个问题图片来看,问题图片一,迁移过程中,正在迁移的key的读写请求缘何避免,问题图片二,迁移过程中的异常(这类 失败,超时)缘何避免。

6.1 Codis扩容迁移细节

【图】迁移流程

影响面:

一阶段期间的影响:通知到通知成功开始英语 英语 期间,proxy读写请求阻塞,不丢失,延时增高(时间极短,并行通知,仅仅修改状况,使proxy中slot状况达到一致)

迁移过程:可读,正在迁移批次的不可写,迁移完成的批次涉及到两次网络io

如上图所示,真是redis平滑迁移过程,主只是我实现了六个点,迁移准备,迁移动作,迁移性能保证。

迁移准备

主只是我在迁移动作执行前,所有的请求都都都还可以 感知到路由的变化,你你这些有了一阶段的避免流程,此处实现是通过并行发送给所有的proxy,proxy会对相应的slot加写锁,你你这些的请求在队列中排队,直到所有的proxy都通知dashboard后后,proxy的锁才放开,此时请求的延回会有轻微增高,但机会是并行响应,影响时间很短,视图会轻微抖动。

迁移动作

主要由dashboard按批次触发直到所有的key都迁移ok,迁移的过程,slot上的key机会地处2种状况,你这些在新的redis实例上A,你这些在旧的redis实例上B,你你这些对于有迁移状况的slot,所有向你你这些slot发送的命令都通过在redis中定制的命令SLOTSMGRT-EXEC-WRAPPER来避免,该命令是基于3.2的分支新增的,该命令主要做这好多个事情,1)判断key不是地处,机会地处,但没了迁移批次,则直接对key调用真实辦法 ,机会地处,但在迁移批次,则允许读操作,不允许写操作,2)机会key不存大,则key机会机会被迁移到新实例,也机会key不地处,则通知proxy前往新的实例进行操作

迁移性能

Codis的迁移真是后后2.x版本的迁移性能不必说高,3.x后后性能提升了非常之大,千万级别的zset形态迁移只时要10多秒,而在原本的模式时要50多秒,具体是因为分析在于

迁移性能数据

6.2 迁移异常避免

另外,想看 这里,我只是我知道让.我都 有越来越那些问题图片,不过这里我准备了你你这些问题图片,来看看codis是如何来避免的,很重在网络环境复杂化,不稳定的状况下缘何操作

问题图片一,把大key拆分成小批次进行迁移,机会批次迁移失败,超时,缘何做?

让.我都 知道分布场景下网络调用有三态,成功,失败,超时,对于失败还好你你这些,超时的状况,让.我都 都时要盲目进行重试,这里显然不行,通常对于数据层面的重试,让.我都 时要保证一一六个非常重要的原则,幂等性,只是我在redis形态中除了zset,set,hash,string形态重试理论不必受影响,对于list缘何办?你你这些codis用了你这些比较暴力的辦法 ,批次迁移成功重试时,会先带上一一六个del命令,让目标结点先将key删掉,再进行重试。

问题图片二,带过期时间key迁移过程中,先在目标结点上设置过期时间再传数据,还是先传数据在最后再设置过期时间?

先看一下在目标结点上设置过期时间再传数据的问题图片:传输一半B机器的key过期,后续key就越来越过期时间。不符合让.我都 的期望

再看一下先传数据在最后再设置过期时间的问题图片:机会传输一半Acrash重启,而此时key过期,则数据落在B机器上成僵尸数据,只是我符合让.我都 的期望。那codis如何来做呢?

为了保证迁移过程中的分片在迁移异常时能自动销毁,你你这些每次分片传输的后后,都重置一下key过期时间为90秒(大于超时时间50秒),在key迁移完成后后再重置为真实的过期时间,原本即使迁移过程中Acrash,key过期机会你你这些的异常,分片数据也只会在目标结点上存活90秒就销毁。

问题图片三,迁移过程中Acrash, 此时对应分片的数据一半在A,一半在B,缘何办了?

常在河边走,哪有不挨刀,让.我都 就碰到过codis的一一六个因expire迁移实现不当造成的血案,不过幸好地处在测试环境,此时千万千万不必说拉起A,机会A上机会有旧数据,此回会是因为分析机会迁移完成的key重新迁移,造成B的数据丢失,正确的姿势是A的备机顶上去,继续迁移,机会A的备机真是是异步克隆qq好友好友,但基本接近于A的全量数据,你你这些问题图片不必多。不过所有的迁移过程中,都最好把数据和分片信息备份,以防数据丢失。此时也千万千万必须反向将B的数据迁移回A,机会B上机会残留有每段迁移的数据,会覆盖掉A的全量数据。

问题图片四,为了性能问题图片,都时要A不做备机,不开启AOF和RDB

你你这些也是万万不可,机会A机会crash后后,被织云拉起,则至少一一六个空实例,会清掉备机的数据,造成数据丢失。

七、Codis相关数据

其中压测环境:压测服务器(v4-8-50)+proxy(v4-8-50) +  redis( B5(4 -32-50) )



从上图中都时要看出,当单次获取的数据量越来越大时,proxy的性能下降会非常快,这类 ZRANGE_50的直连的性能是proxy的2倍

八、运维手册及避坑指南

操作注意项:

8.1 主从切换: 每次主从切换后后,都确认一下被切的主机会备机上的conf文件都机会rewriteok。

grep “Generatedby CONFIG REWRITE” -C 10 {redis_conf路径}/*.conf

8.2 迁移数据:关键操作前,备份数据,若涉及切片信息,备份切片信息

A迁移B时间过长的命令查看:连上Acodisserver,命令行中执行slotsmgrt-async-status查看正在迁移的分片信息(尤其是大key),做到心所含数。千万级别的key约20秒左右都时要迁移完成

8.3 异常避免:redis宕机后重启,重启后后加载key快加载完时,页面上报error

是因为分析 机会是宕机后,redis命令写入aof,只写了命令的每段机会事务提交后后只写入了事务的每段命令是因为分析启动失败,此时日志会aof的异常
修复 第一步 备份aof文件

第二步 执行VIP_CodisAdmin/bin中的redis-check-aof –fix appendonly.aof

第三步 重启

8.4 客户端再次出现血块超时

1)网络是因为分析,联系“连线NOC智利于手”,确认链路网络不是再次出现拥塞

2)观察视图,查看监听队列不是溢出

全连接队列的大小取决于:min(backlog, somaxconn) ,backlog是在socket创建的后后传入的,somaxconn是一一六个os级别的系统参数,基于命令ss -lnt,观察监听队列目前的长度不是与预期一致,

调整参数:vim /etc/sysctl.conf net.core.somaxconn=1024   sysctl -p

3)慢查询,slowlogget,确认不是有耗时操作执行,现网默认是10ms

slowlog-log-slower-than和slowlog-max-len

其中注意:慢查询不所含请求排队时间,只所含请求执行时间,你你这些有机会是redis你这些排队是因为分析的问题图片,但通过慢查询机会查没了来

8.5 fork耗时高

是因为分析 1)当Redis做RDB或AOF重写时,一一六个必不可少的操作只是我执行fork操作创建子线程池池,真是fork创建的子线程池池不时要拷贝父线程池池的物理内存空间,只是我会克隆qq好友好友父线程池池的空间内存页表,都时要在info stats统计中查latest_fork_usec指标获取最近一次fork操作耗时,单位(微秒)。
改善 1)优先使用物理机机会高效支持fork操作的虚拟化技术。

2)控制redis单实例的内存大小。fork耗时跟内存量成正比,线上建议每个Redis实例内存控制在10GB以内。

3)适度放宽AOF rewrite触发时机,目前线上配置:auto-aof-rewrite-percentage增长50 %

子线程池池开销

监控与优化

cpu

不必说和你你这些CPU密集型服务部署在一起去,造成CPU过度竞争

机会部署多个Redis实例,尽量保证同一时刻只一一六个子线程池池执行重写工作

1G内存fork时间约20ms

内存

背景:子线程池池通过fork操作产生,占用内存大小等同于父线程池池,理论上时要两倍的内存来完成持久化操作,但Linux有写时克隆qq好友好友机制(copy-on-write)。父子线程池池会共享相同的物理内存页,当父线程池池避免写请求回会把要修改的页创建副本,而子线程池池在fork操作过程中共享整个父线程池池内存快照。

Fork耗费的内存相关日志:AOF rewrite: 53 MB of memory used by copy-on-write,RDB: 5 MB of memory used by copy-on-write

关闭巨页,开启后后,克隆qq好友好友页单位从原本4KB变为2MB,增加fork的负担,会拖慢写操作的执行时间,是因为分析血块写操作慢查询

“sudo echo never>/sys/kernel/mm/transparent_hugepage/enabled

硬盘

不必说和你你这些高硬盘负载的服务部署在一起去。如:存储服务、消息队列

8.6  AOF持久化细节

常用的同步硬盘的策略是everysec,用于平衡性能和数据安全性。对于你你这些辦法 ,Redis使用另三根线程池池每秒执行fsync同步硬盘。当系统硬盘资源繁忙时,会造成Redis主线程池池阻塞。

1)主线程池池负责写入AOF缓冲区(源码:flushAppendOnlyFile)

2)AOF线程池池负责每秒执行一次同步磁盘操作,并记录最近一次同步时间。

3)主线程池池负责对比上次AOF同步时间:

机会距上次同步成功时间在2秒内,主线程池池直接返回。

机会距上次同步成功时间超过2秒,主线程池池将调用write(2)阻塞,直到同步操作完成

备注:打开AOF持久化功能后,Redis避免完每个事件回会调用write(2)将变化写入kernel的buffer,机会此时write(2)被阻塞,Redis就必须避免下一一六个事件。Linux规定执行write(2)时,机会对同一一六个文件正在执行fdatasync(2)将kernel buffer写入物理磁盘, write(2)会被Block住,整个Redis被Block住。

通过对AOF阻塞流程都时要发现一一六个问题图片:

1)everysec配置最多机会丢失2秒数据,时要1秒。

2)机会系统fsync缓慢,机会是因为分析Redis主线程池池阻塞影响传输速率。

Redis提供了一一六个自救的辦法 ,当发现文件有在执行fdatasync(2)时,就先不调用write(2),只地处cache里,免得被Block。但机会机会超过两秒都还是你你这些样子,则会硬着头皮执行write(2),即使redis会被Block住。

Asynchronous AOF fsync is taking too long (disk is busy). Writing the AOF buffer,without waiting for fsync to complete, this may slow down Redis

8.7 不小心手抖执行了flushdb

机会配置appendonlyno,很快调大rdb触发参数,只是我备份rdb文件,若备份失败,赶紧跑路。配置了appedonlyyes, 辦法 调大AOF重写参数auto-aof-rewrite-percentage和auto-aof-rewrite-minsize,机会直接kill线程池池,让Redis必须产生AOF自动重写。·拒绝手动bgrewriteaof。备份aof文件,一起去将备份的aof文件中写入的flushdb命令干掉,只是我还原。若还原不了,则依赖于冷备。

8.8 线上redis想将rdb模式加带aof模式

切不可,直接修改conf,重启

正确辦法 :备份rdb文件,configset的辦法 打开aof,一起去configrewrite写回配置,执行bgrewriteof,内存数据备份至文件

九、参考资料

Redis开发与运维(付磊)

Redis设计与实践(黄健宏)

大规模codis集群的治理与实践