分布式锁调研

分布式锁调研


导言:分布式锁,是控制分布式系统之间同步访问共享资源的一种方式。调研目标是找到一种合适的DLM (Distributed Lock Manager)方法,主要考虑性能和可用性。下面是调研的几种方法,优劣对比。

数据库锁

思想:使用订单号(唯一)作为数据库表的主键或索引,每笔订单在访问共享资源时,通过下面的方法来保证互斥。

// 获取锁
int lock() {
    return sql.exec("insert into t_dlm(f_oid, f_remark) values('1', 'task1')");
}
// 释放锁
int unlock() {
    return sql.exec("delete from t_dlm where f_oid='1'");
}
// 超时清理
int timeout_op() {
    ttl = "-00:05:00";
    return sql.exec("delete from t_dlm where f_update_time < ADDTIME(NOW(), ttl)");
}

优点
* 实现简单。

缺点
* 对数据库可靠性要求高。
* 对性能要求不高。

Redis实现分布式锁

SET/DEL

SETNX(SET if Not eXists)或者SET(EX/PX/NX/XX,Redis 2.6.12)+DEL,实现分布式锁。

  • Instead of setting a fixed string, set a non-guessable large random string, called token.
  • Instead of releasing the lock with DEL, send a script that only removes the key if the value matches.

phpredis的例子:

<?php

// 锁超时时间5分钟
$ttl = 300;
$ok = $redis->set($key, $token, array('nx', 'ex'=>$ttl));
if ($ok) {
    // 互斥操作
    $job->work();

    // 执行完释放锁
    if ($redis->get($key) == $token) {
        $redis->del($key);
    }
}

?>

优点
* 并发能力强。
* 简单的锁定原语。

缺点
* 存在单点(单实例),锁数据可能丢失(Master和Slave是异步复制),可用性不高。

Redlock

为了提高可用性,redis作者提出了Redlock算法。例如,当存在5个独立的redis节点时,可以允许在最多挂掉2个节点的情况下,分布式锁服务仍然可以正常工作。

算法描述:
we set N=5, which is a reasonable value, so we need to run 5 Redis masters on different computers or virtual machines in order to ensure that they’ll fail in a mostly independent way. In order to acquire the lock, the client performs the following operations:

  1. It gets the current time in milliseconds.
  2. It tries to acquire the lock in all the N instances sequentially, using the same key name and random value in all the instances. During step 2, when setting the lock in each instance, the client uses a timeout which is small compared to the total lock auto-release time in order to acquire it. For example if the auto-release time is 10 seconds, the timeout could be in the ~ 5-50 milliseconds range. This prevents the client from remaining blocked for a long time trying to talk with a Redis node which is down: if an instance is not available, we should try to talk with the next instance ASAP.
  3. The client computes how much time elapsed in order to acquire the lock, by subtracting from the current time the timestamp obtained in step 1. If and only if the client was able to acquire the lock in the majority of the instances (at least 3), and the total time elapsed to acquire the lock is less than lock validity time, the lock is considered to be acquired.
  4. If the lock was acquired, its validity time is considered to be the initial validity time minus the time elapsed, as computed in step 3.
  5. If the client failed to acquire the lock for some reason (either it was not able to lock N/2+1 instances or the validity time is negative), it will try to unlock all the instances (even the instances it believed it was not able to lock).

优点
* 安全性,可用性更高。

缺点
* 获取锁的时间成本增加。

ZooKeeper

思想:客户端一起竞争写某条数据,例如,/path/lock。只有第一个客户端能写入成功,其他的客户端都会写入失败。写入成功的客户端就获得了锁,写入失败的客户端,注册watch事件(阻塞锁),等待锁的释放,从而继续竞争该锁。

Created with Raphaël 2.1.0 开始 尝试获取锁 是否已经被其他事务获取? 等待锁 创建lock临时节点 是否创建成功? 占用锁 完成事务逻辑/事务中断 释放锁 End yes no yes no

优点
* 技术成熟,很多大公司(eBay, Yahoo等)在用。
* 周边工具完善。

缺点
* 复杂。(ZooKeeper is not for the faint of heart. It is pretty heavy and will require you to maintain a fairly large stack.)
* 使用Java涉及的依赖较多。(not that we especially hate Java, but it is on the heavy side and introduce a lot of dependencies. We wanted to keep our machines as lean as possible and usually shy away from dependency heavy technologies.)
* 对Apache发展缓慢的吐槽

Etcd

思路:etcd使用Raft算法保持了数据的强一致性,从而可以用于实现分布式锁。由于Raft算法在做决策时需要多数节点的投票,所以etcd一般部署集群推荐奇数个节点,推荐的数量为3、5或者7个节点构成一个集群。

etcd提供了一套实现分布式锁原子操作CAS(CompareAndSwap)的API。通过设置prevExist值,可以保证在多个节点同时去创建某个目录时,只有一个成功。而创建成功的用户就可以认为是获得了锁。所有想要获得锁的用户都会被安排执行,但是获得锁的顺序也是全局唯一的,同时决定了执行顺序。

优点
* 使用Go语言编写部署简单。
* 使用HTTP作为接口使用简单。
* 使用Raft算法保证强一致性易于理解。
* 数据持久化。
* 支持SSL客户端安全认证。

缺点
* Still not a perfect match, especially in the way that data is spread.

pic

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值