并发

1.redis实现多用户抢票

redis虽然是单线程设计,但存在多个redis客户端,为了保证数据库原子性,其采用WATCH+MULTI 的乐观锁设计。WATCH监听对象,当对象数据发生改变时进行判断,成功则执行,不成功则打断事务,返回nil。
采用Python的threading和Redis模拟多个用户同时抢票,可以看到,用户4属实非酋,要不是手速快,多抢几次就gg了。
并发

2.消息队列与秒杀抢购

秒杀场景下高并发的写请求不是持续的,也不是经常发生的,而只有在秒杀活动开始后的几秒或者十几秒时间内才会存在,因此分库分表的设计并不划算。
常见设计思想:将秒杀请求暂存在消息队列中,然后业务服务器会响应用户一条定好的msg,释放了系统资源之后再处理其它用户的请求。
消息队列还有一个好处是解耦合(比如秒杀活动的数据分析,可以将数据发送到消息队列中,让数据分析系统去订阅),这样一些业务可以异步处理(比如秒杀业务中的第一业务是生成订单,减库存,次要业务是增加用户积分等,可以让积分计算服务器去订阅消息队列的数据)。

并发
但是,数据在消息队列中会存在延迟情况,我只用过kafka的消息队列,一个 Topic(话题)可以配置多个 Partition(分区),Kafka 约定一个分区只能被一个消费者消费(如果有多个 consumer(消费者)可以消费一个分区的数据,那么在操作这个消费进度的时候就需要加锁,可能会影响性能)。那么,可以通过增加分区,增加消费者数量来减少消息延迟。
并发

【题外话】
其实之前学习这方面资料的时候,看到不少人说如果秒杀的库存有限,例如1000库存,会直接通过限流等方式将绝大部分请求挡在服务器之外,真正能进入服务器计算的数据量是很少的,O(∩_∩)O哈哈~,难怪我从来么没抢到过,原来这是幸运抽奖活动。

3. 横向扩展

一个比较烧钱的方法就是横向扩充服务器,采用一个负载均衡服务器(比如Nginx)作为流量的入口,实现流量的分发,将负载(访问的请求)“均衡”地分配到多个处理节点上,减少单个处理节点的请求量。
并发
负载均衡策略:

  • 静态策略:采用轮询等策略,不考虑后台服务器的情况,记录上次请求后端服务的地址或者序号,然后在请求时按照服务列表的顺序,请求下一个后端服务节点
  • 动态策略:采用发送响应包等方法选出最空闲的服务器发送请求。