专车系统给司机派单时,需要过滤掉已经派单的司机,防止出现将不同订单派单给同个司机的情况发生。
以下读写操作均是指redis进行读写。
目前系统里以城市维度保存了每个城市已经处于服务中(已派过订单)的司机列表,但读取城市服务中司机列表和写服务中司机列表时,未进行同步,可能由于高并发,会导致读的司机列表在执行司机筛选时,服务中司机列表被更改。从而出现同个司机派了多个不同的订单的情况发生。
因此考虑两种方式实现
1.使用redis分布式锁实现悲观锁
读取服务中司机列表和写入服务中司机列表使用同一个分布式锁,此时,需要考虑的是如何尽可能缩小锁的范围来降低高并发锁等待
2.使用redis乐观锁
对写入服务中司机列表时,不作锁控制。在读取服务中司机列表时,使用乐观锁实现,即使用watch + redis事务进行读取,若读取结果为空,表示在读取期间,数据发生了变化,因此进行重试即可。
测试
1) 在a窗口执行以下命令,构造初始数据
sadd driver-list 1
sadd driver-list 2
sadd driver-list 3
2) 在b窗口执行以下命令,使用乐观锁+事务方式读取服务中司机列表
watch driver-list
multi
smembers driver-list
3)在a窗口执行命令添加司机 模拟并发导致发生变化的情况
sadd driver-list 4
4) 在b窗口执行exec取事务结果
exec
执行结果为nil表示在事务执行期间,发生了改变,需要进行重试读取,直到成功。
使用乐观锁的方式使系统性能大大提升,重试只有在并发足够高时,才会发生。