Redis高并发分布式锁详解( 八 )


13. 【参考】volatile 解决多线程内存不可见问题 。对于一写多读 , 是可以解决变量同步问题 , 但是如果多写 , 同样无法解决线程安全问题 。如果是 count++操作 , 使用如下类实现:AtomicInteger count = new AtomicInteger(); count.addAndGet(1);如果是 JDK8 , 推荐使用 LongAdder 对象 , 比 AtomicLong 性能更好(减少乐观锁的重试次数) 。了解过源码的都应该知道 AtomicLong和ConcurrentHashMap 都是优化过类似操作的 。那么为何不参考呢?【分段加锁思想
AtomicLong将变量base结合一些数组变量 , 共同维持总数 。面对高并发下 , 是针对单个数组节点进行加锁 , 修改节点内数据 , 而总量依旧是他们加起来 , 而且数组的最大容量与核心数有关 。是不是豁然开朗?这与我们的场景是不是很像 。多台服务器对应多核心 。假设有4台服务器 , 我们是不是可以将变量 redis_promotion_product_stock_$productId :1000 拆解为 redis_promotion_product_stock_$productId_1 :250 , .. , redis_promotion_product_stock_$productId_4 :250 , 
这样的4份(性能好的服务器 , 可以适当偏多) 。那么服务器的CPU是不是就充分利用了 , 而且他们之前的并发问题是不是变小了 。
又或者分成10份 , 每个服务器持有一份 , 用完再去获取新的份额(这种需要额外添加列表维护 , 但是并发冲突再次下降) 。
一旦对某个数据做了分段处理之后 , 就会存在一个问题:假设服务器A的份额消耗完了 , 但是其余服务器还存于份额:
解决方案(处理库存不足的方案是必须要做的):
1.发现这个分段库存里的库存不足了 , 释放锁 , 然后立马换下一个分段库存 , 再次尝试加锁后尝试处理(核心逻辑) 。
     2.依托于负载均衡 , 先判断总库存是否还是有的 , 有的负载到其他服务器 , 要设置好重试次数 。(或者不重试 , 返回友好提示 , 让客户自己去重试 , 毕竟秒杀抢购这东西)
总结1.分布式锁并发优化 , 是一个十分复杂的过程 , 需要考虑数据的拆分 , 如何选择拆分的数据 , 如何校验 , 如何切换等等 。这些都是需要我们考量和积累经验的 。
【Redis高并发分布式锁详解】

经验总结扩展阅读