最近做了一个抢红包的项目,这个项目涉及到了后端开发的多个技术点
- 应用层悲观锁
- 数据库锁机制
- 数据库事务
- 数据库索引
以上这些技术点都是为高并发场景服务的。
应用层悲观锁
为了使抢红包的请求能够依次处理,使用悲观锁将红包预先锁定。需要为该悲观锁设定一个最大生存时间,以确保发生不可预知的错误时,不会影响后续的用户抢红包。其余并发进入的请求将等待并争抢红包锁。一个请求处理完成,将红包解锁,下一个成功获取锁的请求将被处理。
处在等待状态的请求不断争抢红包锁。需设定一个最大重试次数,超时则请求处理过程结束。
实现悲观锁的方案有多种,这里采用了redis的原子操作setnx,setnx返回1代表争抢成功。
数据库锁机制
使用SELECT FOR UPDATE为数据加锁,保证同一时刻只能有一个请求更新数据。在应用层悲观锁的保护下,数据库锁争用、幻读的现象可以减少甚至避免,这样也降低了数据库本身的压力。
数据库事务
抢红包涉及到金钱,在发生异常时需回滚,保证数据一致性。
数据库索引
合理利用数据库索引可以避免不期望的结果。
红包的数据库采用了MySql,分两个表,主表和抢红包记录表。每个用户被限定最多只能抢一次红包,抢红包记录表中的唯一索引(红包id,用户id)可以避免发生意外。
经过应用层悲观锁、数据库锁的保护,发生这种意外的可能性已经微乎其微了。