Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/qq_39662660/article/details/100085677

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

A, Redis what common scenario

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

Two, Redis Pondering

Delay

DB = rear end delay initiation request (a request to copy the user mode kernel mode) + + database network delay addressed and read

If you want to reduce the time delay, you can only reduce the number of requests (to combine multiple backend requests) and reduce database addressing and reading acquisition time. From the perspective of reducing the delay, based on single-threaded and memory of redis, 10 million times per second read and write performance was certainly far better than the disk read and write performance.

Scale data

In a group redis KV Example ( "hello" -> "world"), a simple set of commands ultimately produces four memory consuming structure.

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

For details Redis data store, but also related to the memory allocator (such as jemalloc), it simply is 170 bytes of memory, in fact, memory allocator allocates 192 bytes of storage.

 

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

Then the total cost is

  • A dictEntry, 24 bytes, jemalloc allocates 32-byte memory block
  • A redisObject, 16 bytes, jemalloc allocates 16-byte memory block
  • A Key, 5 bytes, SDS (key) required 5 + 9 = 14 bytes, 16 bytes that jemalloc allocates memory blocks
  • A value, 5 bytes, SDS (value) requires 5 + 9 = 14 bytes, 16 bytes that jemalloc allocates memory blocks

In summary, a need dictEntry 32 + 16 + 16 + 16 = 80 bytes.

 

Third, the kind of Redis distributed solution comparison

 

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

Based on the above comparison, codis as open source products that can demonstrate very intuitive codis low operation and maintenance costs, the smooth expansion of the core strengths.

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

四、Redis分布式解决方案

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

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

五、redis瓶颈和优化

HGETALL

最终存储到redis中的数据结构如下图。

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

采用同步的方式对三个月(90天)进行HGETALL操作,每一天花费30ms,90次就是2700ms!redis操作读取应该是ns级别的,怎么会这么慢?利用多核cpu计算会不会更快?

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

常识告诉我,redis指令执行速度 >> 网络通信(内网) > read/write等系统调用。因此这里其实是I/O密集型场景,就算利用多核cpu,也解决不到根本的问题,最终影响redis性能,**其实是网卡收发数据用户态内核态数据拷贝**

pipeline

这个需求qps很小,所以网卡也不是瓶颈了,想要把需求优化到1s以内,减少I/O的次数是关键。换句话说,充分利用带宽,增大系统吞吐量。

于是我把代码改了一版,原来是90次I/O,现在通过redis pipeline操作,一次请求半个月,那么3个月就是6次I/O。很开心,时间一下子少了1000ms。

 

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

 

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

pipeline携带的命令数

代码写到这里,我不经反问自己,为什么一次pipeline携带15个HGETALL命令,不是30个,不是40个?换句话说,一次pipeline携带多少个HGETALL命令才会发起一次I/O?

我使用是golang的redisgo 的客户端,翻阅源码发现,redisgo执行pipeline逻辑是 把命令和参数写到golang原生的bufio中,如果超过bufio默认最大值(4096字节),就发起一次I/O,flush到内核态。

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

redisgo编码pipeline规则如下图,*表示后面参数加命令的个数,$表示后面的字符长度,一条HGEALL命令实际占45字节。

那其实90天数据,一次I/O就可以搞定了(90 * 45 < 4096字节)!

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

果然,又快了1000ms,耗费时间达到了1秒以内

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

对吞吐量和qps的取舍

笔者需求任务算是完成了,可是再进一步思考,redis的pipeline一次性带上多少HGETALL操作的key才是合理的呢?换句话说,服务器吞吐量大了,可能就会导致qps急剧下降(网卡大量收发数据和redis内部协议解析,redis命令排队堆积,从而导致的缓慢),而想要qps高,服务器吞吐量可能就要降下来,无法很好的利用带宽。

 

六、Redis高可用及容灾处理

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

 

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

 

远程数据热备主要是借助于redis自身具备主从同步的特性,全量同步与增量同步的实现,让redis具体远程热备的能力

 

定期冷备归档由于存储服务在运行的过程中可能存在人员误操作数据,机房网络故障,硬件问题导致数据丢失,因此我们需要一些兜底方案,目前主要是单机滚动备份备份最近48小时的数据以及sng的刘备系统来做冷备,以备非预期问题导致数据丢失,能够快速恢复。

codis的架构本身分成proxy集群+redis集群,proxy集群的高可用,可以基于zk或者l5来做故障转移,而redis集群的高可用是借助于redis开源的哨兵集群来实现,那边codis作为非redis组件,需要解决的一个问题就是如何集成redis哨兵集群。本节将该问题分成三部分,介绍redis哨兵集群如何保证redis高可用,codisproxy如何感知redis哨兵集群的故障转移动作,redis集群如何降低“脑裂”的发生概率。

 

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

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

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

 

七、Redis脑裂处理

脑裂(split-brain)集群的脑裂通常是发生在集群中部分节点之间不可达而引起的。如下述情况发生时,不同分裂的小集群会自主的选择出master节点,造成原本的集群会同时存在多个master节点。,结果会导致系统混乱,数据损坏。

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

由于redis集群不能单纯的依赖过半选举的模式,因为redismaster自身没有做检测自身健康状态而降级的动作,所以我们需要一种master健康状态辅助判断降级的方式。具体实现为

 

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

 

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

 

八、使用Redis趟过的坑

主从切换: 每次主从切换之后,都确认一下被切的主或者备机上的conf文件都已经rewriteok。

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

 

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

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

 

异常处理:redis宕机后重启,重启之后加载key快加载完时,页面上报error

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

客户端出现大量超时

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

fork耗时高

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

不小心手抖执行了flushdb

如果配置appendonlyno,迅速调大rdb触发参数,然后备份rdb文件,若备份失败,赶紧跑路。配置了appedonlyyes, 办法调大AOF重写参数auto-aof-rewrite-percentage和auto-aof-rewrite-minsize,或者直接kill进程,让Redis不能产生AOF自动重写。·拒绝手动bgrewriteaof。备份aof文件,同时将备份的aof文件中写入的flushdb命令干掉,然后还原。若还原不了,则依赖于冷备。

 

线上redis想将rdb模式换成aof模式

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

正确方式:备份rdb文件,configset的方式打开aof,同时configrewrite写回配置,执行bgrewriteof,内存数据备份至文件

粉丝福利

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

 

Tencent Gangster: Share Redis ten billion request for high-availability distributed clusters practice

Above technology can be added JAVA advanced architecture   circles inside Ali, Baidu, reviews, architects live guidance, to enhance their work for 1--5 of Java programmers, as well as architecture learning materials, jvm, handwriting springmvc, distributed, highly available , Redis, data structures, springcloud, springboot obtain

Guess you like

Origin blog.csdn.net/qq_39662660/article/details/100085677