系统设计题

高并发带来的问题:

1. mysql

问题:带来行锁的竞争,导致多个线程等待,数据库每秒处理的消息数降低、响应时间升高,数据库吞吐量降低;导致0.01%的热点数据影响了%99的数据
解决:

  1. 将热点数据放到热点库——坏处:维护麻烦,热点数据迁移+单独的库
  2. 应用层做个队列 排队拿锁排队请求——好处:降低一个机器对数据库的并发度、控制单个商品占据的数据库链接数量
  3. 红包拆分成多个,来增加并发
  4. 合并多条sql对数据库的操作,变成一条——做法:丢到队列里

扣件库存是放mysql中还是缓存?
6. mysql场景:有复杂的扣减库存的逻辑||需要事务
7. redis场景:扣减库存逻辑单一

读操作多的时候是否需要用缓存还是mysql?
场景:秒杀中库存的读、校验逻辑的预读
适用场景:读数据的准确性要求不高的场景;例如:秒杀中库存的读,不需要准确,只用在最终扣减库存的时候兜底数据一致性即可!

缓存使用redis还是localcathe
数据分:静态数据(一直存)、动态数据(定时去更新拉)
redis缓存(30wqps):劣势:需要远程访问,代价高,效率低,且并发度没有localcathe高,也没它快
localcathe适用场景(百万qps):读数据的准确性要求不高的场景(允许脏读,只要最终数据写的时候一致即可),可以每两s拉去redis来更新本地缓存

如何减库存:
下单剪库存:
问题:恶意下单,不买
比预扣库存逻辑简单——适用秒杀场景(基本不会不买)
注意:库存不能为负数,因此字段设置成unsigned,或者》0,或者事务回滚。
下单-付款减库存:超卖(100的库存,300人下单成功,但是200人付款失败)
预扣库存:逻辑复杂——适用普通场景

库存防超卖

  1. 多备库存
  2. (允许少卖)上文提到过,营销券批次的库存数据存放在了 Redis,每次对 Redis 进行库存扣减时,可能会存在网络超时、失败等异常情况,造成扣减库存的结果处于未知状态。当这种情况出现时,我们选择"容忍",认为发券失败,直接结束发券逻辑,不做回滚处理;扣减库存成功后,再为用户实际发券,如果发券失败,此时可以尝试回滚 Redis 库存,因为已经确定本次请求成功扣减了库存,但是回滚失败,不再做额外的重试处理。

其他优化:
多线程

限流&消峰
redis分布式限流(因为队列没法保证流量不会突然进来,所以需要配合限流适用)
限流量:如库存量的1.5倍
消峰:
本地队列:快,不用依赖外部组件
弊端:弊端是内存易失性会使数据无法持久性地存储
解决:

  1. 在应用退出前将内存中的数据处理掉,将队列数据发给其他机器
  2. 兜底补偿-保证最终一致性
    尽管已经实现了应用优雅退出,但是在极端情况下,比如 panic、oom、物理机宕机等异常情况引起的应用退出,应用是接收不到 SIGINT 信号的,也就无法执行优雅退出的业务逻辑。因此我们额外增加了兜底补偿机制,通过定时任务扫表,将卡在中间状态时间较久的数据重新投递到本地队列中进行处理。
    绿色通道-提升用户体验

异步发券的假设是用户从领券动作发生,到实际感知到券的存在,中间是有一段时间缓冲的,但是用户有可能领到券后直接进入春节钱包查看,如果此时异步发券还未完成,有可能会造成客诉。针对这种情况,我们与上游春节主端做了约定,当用户领券后短时间内进入春节钱包查看优惠券时,上游会再次调用发券接口,并增加绿色通道的标识,我们收到这个标识后会将异步发券变更为同步,优先为当前用户发券,保证用户体验。

kafka队列:

热点数据:

热点数据的防治:

  1. 将数据分类,放到不同的redis上
    例如:为了使 Redis 集群流量均匀,不同券批次的库存数据被打散到了不同的 Redis 分片上。
    问题:但是当在一段时间内集中发放某一券批次时,流量仍然会大量偏移到一个分片内,造成 Redis 数据热点问题。如果想办法能将某个券批次多次零散扣减库存的操作合并到一起,那么数据热点问题就可以会得到较大的缓解。
  2. 合并操作成一条
    例如:从二层队列中非阻塞地获取 N 条发券请求数据,如果可以拿到,则将这些数据打包发送到营销资产,如果从队列中拿到的数据小于 N 条,说明此刻队列没有更多的数据,直接将券尽快发出;如果获取不到数据,则随机睡眠一小段时间之后,重新尝试获取,如果经过有限次重试后仍获取不到数据,则结束此次循环。
    营销资产收到合并发券的请求后,会尝试对请求中相同券批次的发券请求进行合并,扣减库存时进行集中扣减,比如之前为 N 个不同用户发放同一券批次 A,每次库存减 1,需要对 Redis 进行 N 次写操作;合并发券后,只需对 Redis 进行 1 次写操作,库存扣减 N 即可。

优化:
热点数据特点:临时的,存活时间短;
队列长度有限,所以采用lru队列淘汰算法。

限制:
防止对其他业务影响;
将热点的请求放到一个队列,防止对其他请求影响

隔离:
业务隔离;
系统隔离;
数据隔离;

同步||异步的选择

A-B-返回用户;
如果B的耗时久的话,可以异步;来满足高效
对于异步带来的失败问题,做兜底方案

兜底

定时任务,来娇艳数据

发红包:

用户领取(高频)+去查询是否入账(低频)
因此给用户发红包可以同步,但是入账的时候异步即可,用户要看的时候再强制入账。

  1. 异步+用户的红包token
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值