积分变动这种业务,可能会有多条业务线同时扣增(增扣、系统发放等)或用户重复提交操作或mq多次消费,导致资源竞争,加锁一般有三种:一种是数据库加个悲观锁(如select .. from update,优点是简单可行,缺点是性能较差),一种是分布式锁(redis、zk,性能较好,缺点是分布式锁本身不安全),还有另外一种,用数据库乐观锁,但要考虑重试机制。
采用 ZooKeeper 实现的分布式锁,在实现原理上与 Redis 有一定的区别,它采用临时序列节点的方式实现公平的分布式锁,并通过 Watcher 机制,避免了释放锁时可能产生的羊群效应。
ZooKeeper 以其强一致性的特点,使得采用它实现的分布式锁安全可靠,不过性能相比 Redis 差一些。
实际使用中可以直接采用 Curator 提供的分布式锁方案,Curator Recipes 库包括了可重入、共享锁、信号量、栅栏等多种实现,方便可靠。
Redis 实现的分布式锁,是通过setnx 来实现的,此命令同样是原子性操作,只有在key不存在的情况下,才能set成功。