> 文章列表 > 常见分布式锁实现原理与使用方法

常见分布式锁实现原理与使用方法

常见分布式锁实现原理与使用方法

        在单体的应用开发场景中涉及并发同步时,大家往往采用Synchronized(同步)或同一个JVM内Lock机制来解决多线程间的同步问题。而在分布式集群工作的开发场景中,就需要一种更加高级的锁机制来处理跨机器的进程之间的数据同步问题,这种跨机器的锁就是分布式锁。

大致分为两种,

        一种是数据库层面的锁,在一段读写期间,无其他线程侵入。

        另一种向上提一级,是锁任务,将某一块代码逻辑锁住。锁去另一种机器拿取,如redis,zookeeper等等。

PS:理论上你可以自己写个单体的管理锁的服务,然后做好各种情况的响应。。。。

线程安全性(原子性、可见性、有序性)

一.单体应用:使用本地锁 + 数据库中的行锁解决

       1.1 synchronized 同步锁范围要比事务的范围大。保证事件的原子性。避免事务还没提交,锁已释放。


public synchronized Long createOrder() throws Exception {TransactionStatus transaction1 = platformTransactionManager.getTransaction(transactionDefinition);Product product = productMapper.selectByPrimaryKey(purchaseProductId);if (product == null) {platformTransactionManager.rollback(transaction1);throw new Exception("购买商品:" + purchaseProductId + "不存在");}//商品当前库存Integer currentCount = product.getCount();//校验库存if (purchaseProductNum > currentCount) {platformTransactionManager.rollback(transaction1);throw new Exception("商品" + purchaseProductId + "仅剩" + currentCount + "件,无法购买");}
​productMapper.updateProductCount(purchaseProductNum, new Date(), product.getId());
​Order order = new Order();// ... 省略 SetorderMapper.insertSelective(order);
​OrderItem orderItem = new OrderItem();orderItem.setOrderId(order.getId());// ... 省略 Setreturn order.getId();platformTransactionManager.commit(transaction1);
}

正确示例:使用Lock

private Lock lock = new ReentrantLock();
​
public Long createOrder() throws Exception{  Product product = null;
​lock.lock();
​TransactionStatus transaction1 = platformTransactionManager.getTransaction(transactionDefinition);try {product = productMapper.selectByPrimaryKey(purchaseProductId);if (product==null){throw new Exception("购买商品:"+purchaseProductId+"不存在");}
​//商品当前库存Integer currentCount = product.getCount();System.out.println(Thread.currentThread().getName()+"库存数:"+currentCount);//校验库存if (purchaseProductNum > currentCount){throw new Exception("商品"+purchaseProductId+"仅剩"+currentCount+"件,无法购买");}
​productMapper.updateProductCount(purchaseProductNum,new Date(),product.getId());platformTransactionManager.commit(transaction1);} catch (Exception e) {platformTransactionManager.rollback(transaction1);} finally {// 注意抛异常的时候锁释放不掉,分布式锁也一样,都要在这里删掉lock.unlock();}
​TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);Order order = new Order();// ... 省略 SetorderMapper.insertSelective(order);
​OrderItem orderItem = new OrderItem();// ... 省略 SetorderItemMapper.insertSelective(orderItem);platformTransactionManager.commit(transaction);return order.getId();
}

二.分布式应用:

        1.使用数据库中的乐观锁,加一个 version 字段,利用CAS来实现

        2.使用数据库维护一张锁的表 + 悲观锁 select,使用 select for update 实现

        3.使用Redis 的 setNX实现分布式锁

        4.使用zookeeper的watcher + 有序临时节点来实现可阻塞的分布式锁

        5.使用Redisson框架内的分布式锁来实现

        6.使用curator 框架内的分布式锁来实现

分布式锁实现原理与最佳实践