苏宁金融红包系统大促海量流量背后的技术支撑
发红包是目前各大互联网公司最常用的营销手段之一,它形式多样,内容丰富。2016 年底苏宁金融开启了红包系统及相关系统的项目开发。
本文将对苏宁金融红包系统的架构部署方式、演变过程、技术优化等方面进行详细阐述。
红包系统的技术挑战
红包,升级版的秒杀系统,红包系统应当具备秒杀系统所具备的特性。
大量用户抢红包带来了系统的高并发压力;大量用户抢同一红包带来了数据一致性问题:红包不能超发,漏发,重复发;而由于红包涉及到资金,也会带来资金安全问题。
由上述可见,一套红包系统,主要的技术挑战在于:系统的高并发,一致性,高响应,安全性等。
红包系统性能优化(高性能&数据一致性)
流量的削峰填谷
削峰填谷:顾名思义,就是在流量洪峰到来之前在系统负载比较低的时候进行数据预热等操作,用来分散红包活动开始后的高并发流量。
红包类营销活动的业务特点:定时的洪峰流量,通过“削峰填谷”有效减少瞬间流量对系统造成的冲击。
开户:用户参与苏宁抢红包活动,均需提前开通红包账户,在红包活动开始后,用户瞬时并发大。
短时间内大量用户参与活动,开通红包账号会将访问请求瞬间提交到后端应用,会给后端的业务系统造成很大的开户压力。
为减轻基础服务压力,将流量峰值进行削峰,我们采取了如下措施:
提前蓄水开户,在活动爆发前,采集近期内的活跃会员进行批量提前开户,降低活动开始时的开户压力。
进入红包活动聚合页提前开户,在用户进入红包活动聚合页时提前开户,降低发红包以及抢红包中的开户压力。
预热活跃用户
流量削峰填谷
异步化
异步红包充值及订单持久化:在红包发放环节,大量用户红包需要到账,如果不对峰值进行处理,压力将会直接转嫁给上游系统造成处理压力,间接导致红包系统堵塞。
因此将充值转为异步处理,先将充值任务进行队列存储,然后分摊到多台机器(利用分布式优点)处理,提升系统处理效率,避免单台节点压力过大。
多级缓存(热点数据全局缓存化)
EHCACHE:本地对读取多,修改少的数据做 EHCACHE 本地缓存处理,减少访问数据库、分布式缓存的次数。
数据库缓存:提高数据库热表的数据缓存大小。
Redis:全局 Redis 数据化处理,利用 Redis 单线程,基于内存读写高 QPS 的特性,解决热点数据高并发,线程安全等一系列问题。
热点数据(包括红包订单,用户发,抢记录等)均存储至 Redis 系统中,并进行多分片部署,通过 Redis 高并发读写的特性,提升系统吞吐量。
另外,目前高并发 Java 系统的核心都是分布式微服务集群部署,这种部署情况下 JVM 级别的锁,线程安全的数据类型等都不适用,那么如何保证红包敏感数据在高并发下的线程安全性呢?
答案还是 Redis,利用 Redis 单线程的处理特性,Redis 在修改数据方面是线程安全的。
以下为红包系统中用到 Redis 存储的部分场景:
Redis Pipeline 管道模式
烟花红包燃放环节对于系统响应时间要求很高。开发初期按照 2000 人参与,5S 响应时间设计,系统已经达到性能需求的要求。
但在活动运营后,易购将活动参与人数提高到了 8888 人,按照原有方案,响应时间变为 13S,耗时大大加长,无法满足性能要求。
在对 Redis 进行大批量的操作时,可以使用 Pipeline 模式,通过减少网络传输时间,从而极大的提高系统性能。
在烟花红包发放中需要对 Redis 进行大量查询操作,在实际测试中发现在对接近 1W 个命令进行循环普通同步模式时需要 10S 左右,而改用 Pipeline 模式后处理时间在 100 毫秒以内。
分布式锁组件
回调式的分布式锁组件
在拆红包环节时可能出现同一用户拆两次红包的问题:当用户点击过快时,可能同一用户的两个线程同时通过了是否拆红包的条件校验,在这种情况下,该用户可以拆两次同一个红包。
针对这一问题,我们通过对红包单号,用户编号两个维度加分布式锁来解决。
目前常用的分布式锁大致有三种实现:
数据库
Zookeeper
Redis
基于实际执行效率和实现难度的考虑,在红包系统使用 Redis 实现了分布式锁组件。
加锁:使用高版本 Redis set 命令的 EX,PX 属性,实现加锁,超时时间设置的原子操作。
加锁
释放锁:通过 Lua 脚本来实现锁值判断,释放锁的原子操作。
释放锁
执行入口
抢红包、拆红包前的高效前置校验
拆红包作为红包操作中并发最高,处理步骤比较复杂的部分,如何削减拆红包的流量至关重要。
抢红包是拆红包大并发流量的第一道入口,系统设计要尽可能满足快进快出的要求。
抢红包流程图
抢红包时只通过缓存计数器做简单的红包状态检验,可以过滤掉大部分拆红包的流量;计数器设置为仅从主 Redis 读,避免随机读的延迟问题。
红包系统高可用架构实践
分布式任务调度
分布式任务调度包括红包超时退款、异常补偿等,红包超过设定时间未被领取完如何退款?红包发放因为系统、网络等各方面的原因,导致用户红包到账失败如何给用户进行补偿?
因为红包涉及到资金问题,所以在红包发放、到账、退款方面需要万无一失,否则可能会遭到用户的大量投诉,在这里我们用苏宁统一任务调度平台进行分布式部署系统的定时任务调度。
定时扫描数据库中符合条件的订单,进行超时退款,发放异常重复订单发放等操作。
支付链路&账户分离
通过设计专用的红包极简收银台、红包账户实现红包发、抢、拆等过程与普通账户、支付链路分离,避免在大促时对支付、会员、账务核心等购物核心主链路造成压力。
高可用部署架构
上图为苏宁金融会员红包系统目前的单集群部署示意图,是典型的苏宁技术体系下的分布式,高可用系统部署结构。
它具备水平扩容,容灾和监控的能力:
前端流量会通过 HLB 来分发和负载均衡至 WAF 平台。
WAF 经过防火墙处理后分发至 HTTP 服务集群(目前主要为 Nginx)。
然后由 HTTP 服务器进行流量反向代理,分发至后端应用服务器进行处理。
服务与服务之间,通过 RPC 远程调用框架进行服务的发现,注册与调用,消息队列使用 Kafka 进行通信。
在存储层使用 Mycat 来访问分布式数据库进行读写操作,分布式缓存使用多分片 Redis 进行存储。
服务器使用 Zabbix 平台进行性能监控,统一任务调度平台进行分布式任务的分发,使用云迹平台进行分布式日志的采集与查看。
为同时应对多个渠道,多种类型的红包类大促营销活动,红包系统采用多个集群部署方式部署,在本次双十一大促中同时为集团各产业红包—奖励金红包、体育红包、圈子红包等营销产品提供高性能高可用的服务支撑。
红包系统的大促保障
红包系统作为公司每次大促营销活动的重要参与系统之一,在 818&双十一等大促中需要应对瞬间海量流量,那么我们如何在大促中监控、保障系统呢?
系统监控
目前在大促活动监控方面,主要分为两大块:
业务监控
中间件监控
业务监控:苏宁金融自研监控平台,可以细化到服务秒级的调用数、成功率、调用耗时等的监控,可以灵活针对各项维度进行告警设置,在业务异常时进行短信或者邮件告警。
业务监控的意义在于实时监控生产线上的流量情况,在流量接近或者超过业务预期的性能阀值后,应当尽快进行服务降级或者生产扩容等紧急措施。
链路式服务监控
中间件监控:中间件的监控平台较多,Zabbix 平台监控服务器的性能指标,包括 CPU 使用率,内存使用率,磁盘使用率,网络流量等。
Redis 监控使用 Promes 监控平台;数据库监控使用苏宁自研数据库管理平台,可实时查看数据库状态,是否存在慢 SQL 等。
异常监管及日志查看使用苏宁自研分布式日志平台,可实时查看分布式系统日志,系统中的异常情况等。
中间件监控可以发现硬件层面的问题,例如系统压力过大时造成 CPU 过高等,可以根据具体指标进行扩容或者联系系统运维解决硬件问题。
多级流控
在流量洪峰来临时,如何优先保障系统稳定呢?首先,通过性能压测等手段确认系统的最大承受能力,为每个服务&接口设定具体的流量阀值。
其后在各级流控平台进行流控配置:
防火墙:防火墙主要针对 HTTP 服务进行流控,并可提供防黄牛、防网络攻击、负载控制等相关功能。
服务全局流控:防火墙仅能针对 HTTP 服务进行流控,那么系统提供的 RPC 微服务接口集群流控则依赖内部流控平台,可提供系统级的全局服务流控。
服务单机流控:RPC 微服务接口单节点流控配置与 RPC 服务后台,提供单机令牌式流控服务。
用户级流控:以上几种流控方式均为服务级别的流控,尚无法控制单个用户的防刷操作,在这里我们开发了基于 Redis 的用户级流控,可以控制单个用户一段时间内的访问次数。
为什么要配置多种级别的流控服务呢?主要基于以下几点考虑:
基于高可用的理念,防止单个流控服务出现故障时可以有其他流控进行补充。
不同流控方式所控制的维度不一样,有针对 HTTP 服务的,有针对 RPC 服务的;级别也不一致,有全局和单机的,在流量控制方面做到万无一失。
控制的方式不一样,有基于 TPS 控制的,也有基于令牌式控制的,还有根据时间范围内次数进行控制。
系统降级
基于 Zookeeper 的分布式配置平台设置应用开关阀值,在系统压力过大时,通过开启关闭非核心应用功能,保障核心主链路的可用。
例如在发红包、抢红包的流量洪峰到来前,通过在配置平台修改开关值,可以暂时性的关闭红包消费功能(余额提现、兑券等),开关关闭后,消费功能暂时不可用,在流量洪峰消退后,打开开关,即可恢复消费功能。
打开和关闭的操作在半分钟内可以完成,快速保护红包核心主链路和恢复功能完整。
未来的挑战及方向
红包系统从 2016 年年底至今,经历了公司的数个大促,目前在业务方面,也面临着一系列的挑战:
随着红包形式的多样化,业务不断提出新的红包玩法;如何在现有能力的基础上,提升系统复用性,核心服务中台化,快速兼容新的红包玩法。
红包系统目前高度依赖 Redis,在现有 Redis 数据持久化的基础上,需要在代码层面进一步完善缓存数据补偿能力。
目前的红包高可用部署基于一个 IDC 机房的集群部署,如果整个 IDC 机房服务都不可用的话,那么服务就需要切换到备机房,目前还无法做到无缝对接;在这种情况下,异地多活部署势在必行。
每年都会有新的红包活动,而随着苏宁易购和苏宁金融用户群体的不断扩大,红包系统面临的挑战也越来越多。
以后我们将围绕高并发,高可用,高一致性的方向,不断优化系统部署,代码结构,未来的路还很长,我们将砥砺前行。
作者:姜春峰、邢恺
简介:姜春峰,苏宁金融研发中心技术副总监,目前负责苏宁金融会员及互联网研发中心的前端、门户、内容、增长产品研发的技术管理工作。具有 8 年互联网金融领域相关研发以及技术管理经验;擅长互联网金融领域应用架构,涉猎支付、理财、保险、营销、生活服务产品等产品领域应用研发,有丰富的系统性能优化经验,具备很强的技术领导力。
邢恺,苏宁金融研发中心技术经理,主要负责苏宁金融会员及互联网研发中心的红包及营销产品线研发工作。具有 7 年软件研发工作经验;参与过苏宁集团多次红包类大促活动的开发;擅长高并发服务端系统开发架构,对构建高性能服务端系统具有比较丰富的实战经验。
编辑:陶家龙、孙淑娟
来源:有投稿、寻求报道意向技术人请联络 editor@51cto.com
精彩文章推荐: