跨JVM的线程安全问题
在单体的应用开发场景中,在多线程的环境下,涉及并发同步的时候,为了保证一个代码块在同一时间 只能由一个线程访问,我们一般可以使用 synchronized 语法和
ReetrantLock
去保证,这实际上是本地锁的方式。
也就是说,在同一个 JVM
内部,大家往往采用
synchronized
或者
Lock
的方式来解决多线程间的安全问 题。但在分布式集群工作的开发场景中,在 JVM
之间,那么就需要一种更加高级的锁机制,来处理种跨 JVM 进程之间的线程安全问题。
解决方案是:使用分布式锁
总之,对于分布式场景,我们可以使用分布式锁,它是控制分布式系统之间互斥访问共享资源
的一种方式。
比如说在一个分布式系统中,多台机器上部署了多个服务,当客户端一个用户发起一个数据插入请求时,如果没有分布式锁机制保证,那么那多台机器上的多个服务可能进行并发插入操作,导致数据重复插入,对于某些不允许有多余数据的业务来说,这就会造成问题。而分布式锁机制就是为了解决类似这类问题,保证多个服务之间互斥的访问共享资源,如果一个服务抢占了分布式锁,其他服务没获取到锁,就不进行后续操作。
大致意思如下图所示(不一定准确):
何为分布式锁?
何为分布式锁?
- 当在分布式模型下,数据只有一份(或有限制),此时需要利用锁的技术控制某一时刻修改数据的进程数。
- 用一个状态值表示锁,对锁的占用和释放通过状态值来标识。
分布式锁的条件:
- 互斥性。在任意时刻,只有一个客户端能持有锁。
- 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
- 具有容错性。只要大部分的 Redis 节点正常运行,客户端就可以加锁和解锁。
- 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
分布式锁的实现:
分布式锁的实现由很多种,文件锁、数据库、redis
等等,比较多;分布式锁常见的多种实现方式:
- 数据库悲观锁、
- 数据库乐观锁;
- 基于Redis的分布式锁;
- 基于ZooKeeper的分布式锁。
在实践中,还是redis
做分布式锁性能会高一些。