本文曾经收录到Github仓库,该仓库蕴含计算机根底、Java根底、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构等外围知识点,欢送star~
Github地址:https://github.com/Tyson0314/...
什么是领劵的订阅推送?就是用户订阅了该劵的推送,在可支付前的一分钟就要把揭示信息推送到用户的app中。具体计划就是到具体的推送工夫点了,coupon零碎调用音讯核心的推送接口,把信息推送进来。
上面咱们剖析一下这个性能的业务情景。公司目前注册用户6000W+,比方有一张无门槛的优惠劵下单立减20元,那么抢这张劵的人就会比拟多,咱们激进预计10W+,百万级别不好说。咱们初定为20W万人,那么这20W条推送信息要在一分钟推送实现!并且一个用户是能够订阅多张劵的。所以咱们晓得了这个订阅性能的有两个突出的难点:
1、推送的实效性:推送慢了,用户会埋怨没有及时告诉他们错过了开抢机会。
2、推送的体量大:爆款的神劵,人人都想抢!
然而推送体量又会影响到推送的实效性。这真是一个让人头疼的问题!
那就让咱们把问题一个个解决掉吧!
推送的实效性的问题:当用户在领劵核心订阅了某个劵的支付揭示后,在后盾就会生成一条用户的订阅揭示记录,外面记录了在哪个工夫点给用户发送推送信息。所以问题就变成了零碎如何疾速实时选出哪些要推送的记录!
- 计划1:MQ的提早投递。MQ尽管反对音讯的提早投递,然而不适宜用来做准确工夫点投递!并且用户执行订阅之后又勾销订阅的话,要把收回去的MQ音讯delete掉这个操作有拍板大,短时间内难以落地!并且用户能够勾销之后再订阅,这又波及到去重的问题。所以MQ的计划否掉。
- 计划2:传统定时工作。这个相对来说就简略一点,用定时工作是去db外面load用户的订阅揭示记录,从中选出以后能够推送的记录。但有句话说得好任何脱离实际业务的设计都是耍流氓。上面咱们就剖析一下传统的定时工作到底适不适宜咱们的这个业务!
是否反对多机同时跑 | 个别不能,同一时刻只能单机跑。 |
---|---|
存储数据源 | 个别是mysql或者其它传统数据库,并且是单表存储 |
频率 | 反对秒、分、时、天,个别不能太快 |
如上表格所示,能够看到个别传统的定时工作存在以下毛病:
1、性能瓶颈。只有一台机在解决,在大体量数据背后力不从心!
2、实效性差。定时工作的频率不能太高,太高会业务数据库造成很大的压力!
3、单点故障。万一跑的那台机挂了,那整个业务不可用了。这是一个很可怕的事件!
所以传统定时工作也不太适宜这个业务。
那有其余解决方案吗?其实能够对传统的定时工作做一个简略的革新即可!把它变成能够同时多机跑,并且实效性能够准确到秒级,并且回绝单点故障的定时工作集群!这其中就要借助咱们的弱小的redis了。
- 计划3:定时工作集群
首先咱们要定义定时工作集群要解决的三个问题!
1、实效性要高
2、吞吐量要大
3、服务要稳固,不能有单点故障
上面是整个定时工作集群的架构图。
架构很简略:咱们把用户的订阅推送记录存储到redis集群的sortedSet队列外面,且以揭示用户揭示工夫戳作为score值,而后在咱们个每业务server外面起一个定时器频率是秒级,我的设定就是1s,而后通过负载平衡之后从某个队列外面获取要推送的用户记录进行推送。上面咱们剖析以下这个架构。
1、性能:除去带宽等其它因素,根本与机器数成线性相关。机器数量越多吞吐量越大,机器数量少时绝对的吞吐量就缩小。
2、实效性:进步到了秒级,成果还能够承受。
3、单点故障?不存在的!除非redis集群或者所有server全挂了。
这里解释一下为什么用redis?
- redis 能够作为一个高性能的存储db,性能要比MySQL好很多,并且反对长久化,稳定性好。
- redis SortedSet队列人造反对以工夫作为条件排序,完满满足咱们选出要推送的记录。
既然计划曾经有了,怎么实现呢?
首先咱们以user_id作为key,而后mod队列数hash到redis SortedSet队列外面。为什么要这样呢,因为如果用户同时订阅了两张劵并且推送工夫很近,这样的两条推送就能够合并成一条,并且这样hash也绝对平均。上面是局部代码的截图:
而后要决定队列的数量,个别失常来说咱们有多少台解决的服务器就定义多少条队列。因为队列太少,会造成队列竞争,太多可能会导致记录得不到及时处理。
然而最佳实际是队列数量应该是可动静配置化的,因为线上的集群机器数是会常常变的。大促的时候咱们会加机器是不是,并且业务量增长了,机器数也是会减少是不是~。所以我是借用了淘宝的diamond进行队列数的动静配置。
咱们每次从队列外面取多少条记录也是能够动静配置的
这样就能够随时依据理论的生产状况调整整个集群的吞吐量。 所以咱们的定时工作集群还是具备一个个性就是反对动静调整。
最初一个要害组件就是负载平衡了。这个是十分重要的!因为这个做得不好就会可能导致多台机竞争同时解决一个队列,影响整个集群的效率!在工夫很紧的状况下我就用了一个简略的计划,利用redis一个自增key,而后 mod 队列数量算法。这样就很大水平上就保障不会有两台机器同时去竞争一条队列。
最初咱们算一下整个集群的吞吐量
10(机器数) * 2000(一次拉取数) = 20000。而后以MQ的模式把音讯推送到音讯核心,发MQ是异步的,算上其它解决0.5s。
其实发送20W的推送也就是10几s的事件。
到这里咱们整个定时工作集群就差不多根本落地好了。反过来认真思考了一下,有以下能够优化的点:
1、加监控, 集群怎么能够木有监控呢,万一出问题有工作沉积怎么办。
2、加上可视化界面。
3、最好有智能调度,减少工作优先级。确保优先级高的工作先运行。
4、资源调度,万一机器数量不够,力不从心,优先保障重要工作执行。
目前我的项目已上线,运行稳固。
最初给大家分享一个Github仓库,下面有大彬整顿的300多本经典的计算机书籍PDF,包含C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,能够star一下,下次找书间接在下面搜寻,仓库继续更新中~
Github地址:https://github.com/Tyson0314/...