目录
1. 前言
本文专注介绍REdis实践过程研究和总结出实用性技巧,以期帮忙更好的使用REdis。内容持续更新中,如有需要可多关注。
2. REdis队列应用
2.1. 队列介绍
REdis有两种类型的队列,一是传统的list队列,另一是5.0版本引入的类Kafka的stream队列,一份数据多消费推荐使用stream队列。
2.2. 队列作用
使用队列常是为达到两个目的:
1) 堆积消息
2) 上下游解耦
堆积消息能力可以保证下游系统,让下游可从容处理,而且也方便监控了解负载。同时,也解耦了上下游,上游只需要根据约定好的数据结构往队列中塞数据即可,而下游则不必关心上游,只需专注队列中是否有数据。
2.3. 应用原则
1) 逻辑队列分成多个物理队列
好得是提升并发性能,并且增加了容错能力。
2) 独立部署REdis(或集群)做队列
原因是队列类型重写AOF代价小效率高,这是因为通常队列中积累的数据量小,可快速完成AOF的重写。
重写AOF或RDB是影响REdis稳定性的重要因此,特别是对于集群版本的REdis。使用独立的REdis(或集群),可以有效的提升队列服务的稳定性,这样不至于因为REdis的稳定性影响到上游。
关键措施:队列独占REdis或REdis集群。
3. REdis大Key问题
本问题只针对REdis集群,其常见的大Key有:
1) 整个平台或系统的数据统计;
2) REdis队列。
单个Key不但一会成为性能瓶颈,还会降低系统可用性。REdis的单线程实现架构,导致单个Key的处理性能有限,而且如果该Key归属的REdis节点异常,也直接导致不可用。
为此常规做法将单个大的逻辑Key分成小的若干个物理Keys,这些物理Keys有相同的前缀,不同的下标,比如共同前缀为“plat:”,分成5个Keys,则五个物理Keys分别为:plat:0、plat:1、plat:2、plat:3和plat:4。
这样做法简单明了,但容易遇到Keys倾斜问题,即物理Keys在不同节点间分布不均衡,甚至容易出现某个节点负责的Keys数是其它节点的两倍或更大倍数。
这个时候可将单个大的逻辑Key分成更多的物理Keys以增强均衡性,但这同时也带了一个副作用,即查询代价线性提升,为查汇总数据,需要同时查更多数量的物理Keys。
针对这个问题,常可采用缓存方式缓解问题,以减少查询大量物理Keys的次数,这都是下下策。
稍微变通一下,大的原则不变,仍然是将一个大的逻辑Key分成多个小的物理Keys,这些Keys也保持相同前缀(实际也可以不同,但相同方便管理),但下标不再连续,而是采用配置方式。由于采用了配置方式,那么可以事先在目标REdis集群上测试,保证每个主节点只会有一个Key,这样就完全均衡了,而且实现了Keys数量的最小化即均衡。新的方式,对应的物理Keys可能分别是:plat:0、plat:2、plat:3、plat:6和plat:9,分解的目标是每一个主节点一个Key,没必要一个主节点多个Keys,因为多个反而增加了查询的负担。
如果采用轮询方式访问Keys,则会偶发性出现访问倾斜,即某一时刻都轮询到了同一个Key。对一这种情况,可采取“亲和性”,即Key和处理进程或线程建立亲和关系,只有在访问异常时才访问非亲和关系的Keys。
队列的应用也可基于这个方法去改造,使得队列均衡分布,最大化发挥集群性能和提升可用性。
关键措施:人工确定逻辑大Key的物理组成Keys。
4. AOF和RDB选择
AOF相比RDB有更高的可靠性,可以防止丢失更少的数据。一般没有必要同时开启AOF和RDB,因为现有的REdis实现下,如果开启了AOF,实际上是不会用到RDB的,因此只会增强写负担。以下是redis-5.0.5的加载AOF或RDB代码片段:
/* Function called at startup to load RDB or AOF file in memory. */ void loadDataFromDisk(void) { long long start = ustime(); // 配置文件redis.conf中的appendonly值为yes时,值为AOF_ON否则为AOF_OFF if (server.aof_state == AOF_ON) { // 加载AOF文件 if (loadAppendOnlyFile(server.aof_filename) == C_OK) serverLog(LL_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000); } else { rdbSaveInfo rsi = RDB_SAVE_INFO_INIT; if (rdbLoad(server.rdb_filename,&rsi) == C_OK) { 。。。。。。 } |
实际上从REdis-4.0版本开始,新增了AOF和RDB混合模式,实现方式是AOF文件增加了文件头,紧挨文件头部分是RDB格式数据,最后跟AOF格式数据。开启AOF和RDB混合模式,只需设置配置项aof-use-rdb-preamble值为yes(REdis-4.0默认为no,REdis-5.0默认为yes)。
正常情况下从节点启动时,总是从主节点全量同步数据,主节点为此会生成RDB文件,而REdis-5.0开始支持不生成RDB文件的全量同步方式,只需要将配置项repl-diskless-sync的值设置为yes。
5. repl-backlog-size大小设置
REdis通过配置项repl-backlog-size控制环型复制缓冲区(repl-backlog)的大小,一个节点只有一个环型复制缓冲区,所有从节点(Slaves)共享,因此它所耗费的内存开销还好。
环型复制缓冲区的作用是从节点(从REdis-5.0开始叫复制节点)断开后重连接,从环型复制缓冲区读取落后的数据,从而避免了全量复制。因此repl-backlog-size的大小直接关系主节点可容忍从节点断开连接的时长,默认1MB通常是不能满足生产环境的,因此可以根据实际设置成较大的值。