多线程情况下对共享资源的操作需要加锁,避免数据被写乱,在分布式系统中,这个问题也是存在的,此时就需要一个分布式锁服务。常见的分布式锁实现一般是基于DB、Redis、zookeeper。下面笔者会按照顺序分析下这3种分布式锁的设计与实现,想直接看分布式锁总结的小伙伴可直接翻到文档末尾处。
分布式锁的实现由多种方式,但是不管怎样,分布式锁一般要有以下特点:
- 排他性:任意时刻,只能有一个client能获取到锁
 - 容错性:分布式锁服务一般要满足AP,也就是说,只要分布式锁服务集群节点大部分存活,client就可以进行加锁解锁操作
 - 避免死锁:分布式锁一定能得到释放,即使client在释放之前崩溃或者网络不可达
 
除了以上特点之外,分布式锁最好也能满足可重入、高性能、阻塞锁特性(AQS这种,能够及时从阻塞状态唤醒)等,下面就话不多说,赶紧上(开往分布式锁的设计与实现的)车~
DB锁
在数据库新建一张表用于控制并发控制,表结构可以如下所示:
CREATE TABLE `lock_table` ( `id` int(11) unsigned NOT NULL COMMENT '主键', `key_id` bigint(20) NOT NULL COMMENT '分布式key', `memo` varchar(43) NOT NULL DEFAULT '' COMMENT '可记录操作内容', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`,`key_id`), UNIQUE KEY `key_id` (`key_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
key_id作为分布式key用来并发控制,memo可用来记录一些操作内容(比如memo可用来支持重入特性,标记下当前加锁的client和加锁次数)。将key_id设置为唯一索引,保证了针对同一个key_id只有一个加锁(数据插入)能成功。此时lock和unlock伪代码如下:
def lock : exec sql: insert into lock_table(key_id, memo, update_time) values (key_id, memo, NOW()) if result == true : return true
