整体需要解决三个问题
- 高性能
- 高可用
- 一致性
高性能
- 动静分离
- 数据拆分
动态数据和静态数据区分开来,比如:- 用户:身份信息,偏好推荐、广告、异步的方式加载。
- 时间:秒杀时间由服务端统一管控,可以通过动态请求进行获取
- 静态缓存
- url唯一化
- 缓存方式的选择
浏览器:第一选择,但是用户不主动刷新,无法实现消息实时推送,简单的业务可以选择此种方式
CDN:失效问题和高命中率的问题,选择CDN节点、节点数量都会影响实际效果
服务端:使用Redis做缓存,nginx服务
小结: 数据量减少,减少没必要的请求;路径尽量短,以便提高单次请求效率。
- 热点优化
-
热点操作
热点操作是用户的行为,不好改变,但可以做一些限制保护,比如用户频繁刷新页面进行提示阻断。
零点刷新、零点下单、零点添加购物车都属于热点操作。 -
热点数据
热点识别:- 静态热点:可以预测到的热点商品。可以通过买家报名的方式和统计sku访问量来统计出热点商品
- 动态热点:不可预测的热点商品。因为某种不确定因素导致商品需求增加,比如一条广告,或者一次推广。
- 总结:因此热点数据需要动态的发现能力,常见的实现思路是:异步采集各个环节KEY信息,如nginx采集访问url,采集热点日志;聚合分析热点数据,当某种商品访问达到一定规则,各系统根据自身需求决定如何处理热点数据。
-
热点隔离:
将热点数据隔离出来,不能让这1%的操作影响到了99%的业务
业务隔离:系统可以提前对热点做缓存预热
系统隔离:运行时隔离,秒杀接口单独设计,单独部署
数据隔离:启用单独的缓存集群或者DB服务 -
热点优化:
缓存:热点数据缓存
限流:流量限制保护
小结: 热点优化是基于二八原则对数据进行了纵向拆分,以便进行针对性的处理。
- 系统优化
- 较少序列化
- 减少IO
总结: 性能优化需要一个基准值,所以系统还需要做好应用基线,比如性能基线(何时性能突然下降),成本基线(去年大促用了多少机器),链路基线(核心流程发生了哪些变化),通过基线持续关注系统性能,促使系统在代码层面持续提升编码质量、业务层面及时下掉不合理调用、架构层面不断优化改进。
一致性
- 减库存方式和问题
- 下单减库存
用户最好用也最为简单的方式 - 付款减库存
付款成功扣减库存,高并发容易导致付款失败 - 预扣库存
库存为其保留一定时间(如15分钟)
- 实际如何减库存
下单减库存的问题:恶意卡单,导致商品卖不出去
付款减库存的问题:用户体验最差,会导致用户下单成功缺无法付款的情况
预扣库存:这种方式最合理,在下单后,设置订单有效期。但是还是无法杜绝那种恶意下单的买家。 - 一致性性能优化
这是秒杀系统最关键的核心难题,高读高写- 高并发读
解决高并发读问题的关键是“分层校验”,只进行不影响性能的检查操作,如:用户秒杀资格、商品状态是否正常,秒杀是否结束、用户答题是否正确、是否非法请求。直到写链路时,才对库存做一致性检查;允许读场景下一定的脏数据,在高可用和一致性之间做一个平衡。
核心思想就是尽量过滤掉无效请求,只在漏斗最末端进行有效处理 - 高并发写
更换读写DB选型:比如用Redis来做这一时段的存储。
优化DB性能:- 应用层排队:
通过缓存加入集群分布式锁,从而控制集群对数据库同一行记录进行操作的并发度 - 数据层排队:
应用层排队有损性能,数据层排队是最为理想的。业界中AliSQL做了补丁程序。
- 应用层排队:
- 高并发读
高可用
- 流量削峰
人为的延缓秒杀请求,甚至可以过滤掉一些无效请求。有以下方式:
- 答题
1.1 防止作弊。机器人秒杀
1.2 延缓请求。减少高峰期的并发压力 - 排队
2.1 请求积压
2.2 用户体验较差 - 过滤
核心结果在于分层,通过在不同层次过滤掉无效请求,达到数据读写的精准触发。
3.1 读限流:将超出系统承载能力的请求过滤掉
3.2 读缓存:对读请求做缓存,将重复的请求过滤掉
3.3 写限流:对写请求做限流保护
3.4 写校验:对写请求做一致性校验只保留最终有效数据