0%

并发控制

并发场景

秒杀场景,多人并发申请购买同一种商品。
下面以2人抢购同一件商品举例,商品数量为1。
基本流程如下:

这个流程中存在明显的并发问题,当进程A查看有1个商品,但未开始创建购买记录,此时另一个进程B也进行了资源检查,发现有1个商品,顺利通过,并完成购买操作,此时A继续执行,则1个商品会产生两条购买的记录。(这个并发场景很简单,很普遍)

解决方案

解决方案通常是2类:
1 通过将请求分发到不同set,减少并发的可能性,分而治之。这里暂时不讨论。
2 当收到并发请求时,如何处理。

加锁操作先占有锁资源,再占有资源

a. 锁库存
b. 插入“秒杀”记录
c. 更新库存

“秒杀”系统的设计难点就在这个事务操作上。商品库存在DB中记为一行,大量用户同时“秒杀”同一商品时,第一个到达DB的请求锁住了这行库存记录。在第一个事务完成提交之前这个锁一直被第一个请求占用,其他到达的请求全部失败。

加锁的方案,效率会比较低。实际应用时,通常要配合排队系统,让没有获取到锁的请求排队。

单独开发请求排队调度模块

排队模块接收用户的抢红包请求,以FIFO模式保存下来,调度模块负责FIFO队列的动态调度,一旦有空闲资源,便从队列头部把用户的访问请求取出后交给真正提供服务的模块处理。优点是,具有中心节点的统一资源管理,对系统的可控性强,可深度定制。缺点是,所有请求流量都会有中心节点参与,效率必然会比分布式无中心系统低,并且,中心节点也很容易成为整个系统的性能瓶颈。

巧用Redis 特性,使其成为分布式序号生成器(我们最终采用的做法) – 具体还要再看,如何利用redis的特性

参考
https://www.ibm.com/developerworks/cn/web/wa-design-small-and-good-kill-system/index.html
https://blog.csdn.net/zhanjianshinian/article/details/53342730
每件商品以一个数字ID来标识,这个ID是全局唯一的,所有围绕商品的操作都使用这个ID作为数据的关联项。

Redis节点内存储的是这个分组可以分发的商品ID号段,利用Redis特性实现红包分发,各服务节点通过Redis原语获取当前拆到的红包。这种做法的思路是,Redis 本身是单进程工作模型,来自分布式系统各个节点的操作请求天然的被 Redis Server 做了一个同步队列,只要每个请求执行的足够快,这个队列就不会引起阻塞及请求超时。而本例中我们使用了 DECR 原语,性能上是可以满足需求的。Redis 在这里相当于是充当一个分布式序号发生器的功能,分发红包 ID。

通过memcached来控制并发数 – 具体还要再看

https://blog.csdn.net/echo3/article/details/17580347 使用memcached进行并发控制(写的非常好)
http://www.infoq.com/cn/articles/2017hongbao-weixin# 百亿级微信红包的高并发资金交易系统设计方案
https://blog.csdn.net/yanker1990/article/details/78737626 Memcache的并发问题和利用CAS的解决方案

参考

如何设计一个小而美的秒杀系统?
https://www.ibm.com/developerworks/cn/web/wa-design-small-and-good-kill-system/index.html
使用memcached进行并发控制(写的非常好)
https://blog.csdn.net/echo3/article/details/17580347
电商秒杀系统设计分析
https://blog.csdn.net/zhanjianshinian/article/details/53342730

https://memcached.org/about
Redis DECR命令
https://www.kancloud.cn/thinkphp/redis-quickstart/36180

云主机的问题:
申请时要排队,好像没有意义。
防止申请到同一台宿主机,前面做的临时添加资源是否有用。跟定时更新是否有冲突?