现在我们写的程序基本上都有一定的并发性,要么单台多进线程、要么多台机器集群化,在仅读的场景下是不需要加锁的,因为数据是一致的,在读写混合或者写场景下如果不加以限制和约束就会造成写混乱数据不一致的情况。
如果业务安全和正确性无法保证,再多的并发也是无意义的。
凡事基本上都是双面的,锁可以在一定程度上保证数据的一致性,但是锁也意味着维护和使用的复杂性,当然也伴随着性能的损耗。锁使用不当不但解决不了数据混乱问题,甚至会带来诸如死锁等更多问题。
单机锁和分布式锁
锁依据使用范围可以简单分为:单机锁和分布式锁。
单机锁可以实现线程同步和互斥资源的共享,单机锁实现了机器内部线程之间对共享资源的并发控制。
分布式锁是控制分布式系统之间同步访问共享资源的一种方式,用于在分布式系统中协调他们的动作。
分布式锁的实现简介
分布式CAP理论告诉我们需要做取舍:
任何一个分布式系统有三大特性:一致性Consistency、可用性Availability和分区容错性Partition Tolerance,但是由于网络分区不受人为控制,在网络发生分区时,我们必须在可用性和一致性二者中选择之一。
在互联网领域的绝大多数场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只保证最终一致性。在很多场景中为了保证数据的最终一致性,需要很多技术方案来支持,比如分布式事务,分布式锁等。
分布式锁需要具备的条件
-
互斥性
在任意时刻只有一个客户端能持有锁 其他尝试获取锁的客户端都将失败而返回或阻塞等待。
-
健壮性
一个客户端持有锁的期间崩溃而没有主动释放锁,也需要保证后续其他客户端能够加锁成功。
-
唯一性
加锁和解锁必须是同一个客户端。
-
高可用
只要大部分的节点正常运行,客户端就可以进行加锁和解锁操作。
分布式锁的三种实现方式
- 基于数据库
- 在数据库创建一张表,表里包含方法名等字段,并且在方法名字段上面创建唯一索引,执行某个方法需要使用此方法名向表中插入数据,成功插入则获取锁,执行结束则删除对应的行数释放锁。
- 基于Redis
- Redis性能好而且实现方便,但是单节点的分布式锁在故障迁移是产生安全问题,Redlock基于N个完全独立的Redis节点实现分布式锁的高可用。
- 基于Zookeeper
- 以Paxos算法为基础的分布式应用程序协调服务,为分布式应用提供一致性服务的开源组件。
参考
- https://juejin.cn/post/6844904039218429960#heading-0