Reference
[1] https://redis.io/topics/distlock
[2] https://dzone.com/articles/distributed-lock-using
[3] https://en.wikipedia.org/wiki/Distributed_lock_manager
Java的lock只作用于同一个JVM,当有多个instance同时处理requests时,java的锁已不再适用,所以分布式锁已成为必须。
目前分布式锁的实现方式主要有三种
- 基于数据库(不在内存中)
- 基于Zookeeper
- 基于Redis(in memory)
一 基于数据库
我到真是见过一个组用sybase实现分布式锁。具体方式是针对每一个要加锁的object在数据库里建一个entry,表示某个instance正在占有这个object。原理很简单,只需要一个单独的LockMaintenanceService独立于应用之外负责管理。但是具体performance跟数据库相关,一般来说效率不会很好。
二 基于Zookeeper
ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.
用Zookeeper做分布式锁也很常见,具体方式:
For a single task say its id is 10000, lib-zookeeper will create a parent node (with random bytes) in Zookeeper called "task-10000". Suppose "thread-1-1" comses from instance 1, and is trying to get the lock on node "task-10000", lib-zookeeper will create a child node like "task-10000/***sessionId*thread-1-1***" under the parent node and give the lock to thread-1-1. A watcher is created and will be updated each time the zookeeper lock gets released.
So the next time thread-2-1 from instance 2 comes in and trying to acquire the lock, a new child node is created as "task-10000/***sessionId*thread-2-1***" under this parent node. If the lock is not released yet, it will just wait. If thread-1-1 finally releases the lock, the watcher will be notified and then the lock will be assigned to thread-2-1.
Use try lock with timeout to avoid dead lock.
三 基于Redis
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.
Redis比平常数据库的performance要好一些,毕竟in memory。可以用redis实现基于Redlock Algorithm的分布式锁。
四 总结
1. 基于分布式的锁一定要auto release,或者try-lock mechanism避免客户端crash或者死锁
2. 一个instance占用分布式锁的时间不应太长,否则instance越多效率越低,吞吐量越小,timeout越多