Redis 在 vivo 推送平台的应用与优化实践
Posted vivo互联网技术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis 在 vivo 推送平台的应用与优化实践相关的知识,希望对你有一定的参考价值。
作者:vivo互联网服务器团队-Yu Quan
一、推送平台特点
vivo推送平台是vivo公司向开发者提供的消息推送服务,通过在云端与客户端之间建立一条稳定、可靠的长连接,为开发者提供向客户端应用实时推送消息的服务,支持百亿级的通知/消息推送,秒级触达移动用户。
推送平台的特点是并发高、消息量大、送达及时性较高。目前现状最高推送速度140w/s,单日最大消息量150亿,端到端秒级在线送达率99.9%。
二、推送平台Redis使用介绍
基于vivo推送平台的特点,对并发和时效性要求较高,并且消息数量多,消息有效期短。所以,推送平台选择使用Redis中间件作为消息存储和中转,以及token信息存储。之前主要使用两个Redis集群,采用Redis Cluster 集群模式。两个集群如下:
对Redis的操作,主要包括如下几方面:
1)推送环节,在接入层存储消息体到msg Redis集群,消息过期时间为msg Redis存储消息的过期时间。
2)推送服务层经过一系列逻辑后,从msg Redis集群查出消息体,查询client Redis集群client信息,如果client在线,直接推送。如果client不在线,将消息id写到等待队列。
3)如果连接上来,推送服务层,读取等待队列消息,进行推送。
4)存储管理服务,会定期扫描cii索引,根据cii存储的最后更新时间,如果14天都没更新,说明是不活跃用户,会清理该token信息,同时清理该token对应的等待队列消息。
推送环节操作Redis流程图如下:
三、推送平台线上问题
如上面介绍,推送平台使用Redis主要msg集群和client集群,随着业务的发展,系统对性能要求越来越高,Redis出现一些瓶颈问题,其中msg Redis集群在优化前,规模已达到220个master,4400G容量。随着集群规模变大,维护难度增加,事故率变高。特别是4月份,某某明星离婚事件,实时并发消息量5.2亿,msg Redis集群出现单节点连接数、内存暴增问题,其中一个节点连接数达到24674,内存达到23.46G,持续30分钟左右。期间msg Redis集群读写响应较慢,平均响应时间500ms左右,影响到整体系统的稳定性和可用性,可用性降到85%。
四、推送平台Redis优化
Redis一般从以下几方面优化:
1)容量:Redis属于内存型存储,相较于磁盘存储型数据库,存储成本较昂贵,正是由于内存型存储这个特性使得它读写性能较高,但是存储空间有限。因此,业务在使用时,应注意存储内容尽量是热数据,并且容量是可预先评估的,最好设置过期时间。在存储设计时,合理使用对应数据结构,对于一些相对大的value,可以压缩后存储。
2)热key倾斜:Redis-Cluster把所有的物理节点映射到[0-16383]slot(槽)上,每个节点负责一部分slot。当有请求调用时,根据 CRC16(key) mod 16384的值,决定将key请求到哪个slot中。由于Redis-cluster这个特性,每个节点只负责一部分slot,因此,在设计key的时候应保证key的随机性,特别是使用一些hash算法映射key时,应保证hash值的随机分布。另外,控制热点key并发问题,可以采用限流降级或者本地缓存方式,防止热点key并发请求过高导致Redis热点倾斜。
3)集群过大:Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。每个节点都保存所有节点与slot映射关系。当节点较多时,每个节点保存的映射关系也会变多。各节点之间心跳包的消息体内携带的数据越多。在扩缩容时,集群重新进行clusterSlots时间相对较长。集群会存在阻塞风险,稳定性受影响。因此,在使用集群时,应该尽量避免集群节点过多,最后根据业务对集群进行拆分。
这里有个问题:为什么Redis-Cluster使用16384个slot,而不是更多,最多可以有多少个节点?
官方作者给出了解释,并且在解释中说明,Redis-Cluster不建议超过1000个主节点。
基于以上一些优化方向,和自身业务特性,推送平台从以下几方面开启Redis优化之路。
msg Redis集群容量优化;
msg Redis大集群根据业务属性拆分;
Redis热点key排查;
client Redis集群并发调用优化。
4.1 msg Redis集群容量优化
前文提及,msg Redis集群规模达到220个master、4400G容量,高峰期已使用容量达到3650G,使用了83%左右,如果后续推送提量,还需扩容,成本太高。于是对msg Redis集群存储内容进行分析,使用的分析工具是雪球开源RDB分析工具RDR 。github网址:这里不多介绍,大家可以去github网址下载相应的工具使用。这个工具可以分析Redis快照情况,包括:Redis不同结构类型容量、key数量、top 100 largest keys、前缀key数量和容量。
分析后的结论:msg Redis集群中,mi:开头的结构占比80%左右,其中单推消息占比80%。说明:
单推:1条消息推送1个用户
群推:1条消息可以重复推送多个用户,消息可以复用。
单推的特点是一对一推送,推送完或者推送失败(被管控、无效用户等)消息体就不再使用。
优化方案:
及时清理单推消息,如果用户已经收到单推消息,收到puback回执,直接删除Redis消息。如果单推消息被管控等原因限制发送,直接删除单推消息体。
对于相同内容的消息,进行聚合存储,相同内容消息存储一条,消息id做标识推送时多次使用。
经过这个优化后,缩容效果较明显。全量上线后容量缩小了2090G,原最高容量为3650G,容量缩小了58%。
4.2 msg Redis大集群根据业务属性拆分
虽然进行了集群容量优化,但是高峰期msg Redis压力依然很大。
主要原因:
1)连接msg Redis的节点很多,导致高峰期连接数较高。
2)消息体还有等待队列都存储在一个集群,推送时都需要操作,导致Redis并发很大,高峰期cpu负载较高,到达90%以上。
3)老集群Redis版本是3.x,拆分后,新集群使用4.x版本。相较于3.x版本有如下优势:
PSYNC2.0:优化了之前版本中,主从节点切换必然引起全量复制的问题。
提供了新的缓存剔除算法:LFU(Least Frequently Used),并对已有算法进行了优化。
提供了非阻塞del和flushall/flushdb功能,有效解决删除了bigkey可能造成的Redis阻塞。
提供了memory命令,实现对内存更为全面的监控统计。
更节约内存,存储同样多的数据,需要更少的内存空间。
可以做内存碎片整理,逐步回收内存。当使用Jemalloc内存分配方案的时候,Redis可以使用在线内存整理。
拆分方案根据业务属性对msg Redis存储信息进行拆分,把消息体和等待队列拆分出来,放到独立的两个集群中去。这样就有两种拆分方案。
方案一:把等待队列从老集群拆分出来
只需推送节点进行修改,但是发送等待队列连续的,有状态,与clientId在线状态相关,对应的value会实时更新,切换会导致数据丢失。
方案二:把消息体从老集群拆分出来
所有连接msg Redis的节点替换新地址重启,推送节点进行双读,等到老集群命中率为0时,直接切换读新集群。由于消息体的特点是只有写和读两个操作,没有更新,切换不用考虑状态问题,只要保证可以写入读取没问题。并且消息体容量具有增量属性,需要能方便快速的扩容,新集群采用4.0版本,方便动态扩缩容。
方案一 | 方案二 | |
优点 | Redis线程模型的前世今生 vivo 推送平台架构演进 Redis大集群扩容性能优化实践 Redis 内存优化在 vivo 的探索与实践
介绍Redis内存结构及内存管理方式,同时分享一些内存优化建议及内存异常处理相关的优化措施。
介绍Redis内存结构及内存管理方式,同时分享一些内存优化建议及内存异常处理相关的优化措施。
分享 vivo 互联网技术干货与沙龙活动,推荐最新行业动态与热门会议。
以上是关于Redis 在 vivo 推送平台的应用与优化实践的主要内容,如果未能解决你的问题,请参考以下文章 |