面试专题

分布式锁

2019-04-22  本文已影响76人  zhglance

1.分布式CAP原则

在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。因此不同的系统要根据CAP理论做出取舍,绝大多数场景是牺牲一致性来换取系统的高可用性,系统保证最终一致性。

2.分布式锁

在分布式模型下,通过锁机制来让多个客户端互斥的对共享资源进行访问,要求具有排他性,避免死锁性和高可用性。

3.分布式锁的实现

3.1 基于数据库实现

a.基于乐观锁
乐观锁说明:
CAS(V,E,N);
V表示要更新的变量,E表示预期值,N表示新值。
如果V值等于E,则说明还没有其他线程修改V的值,则将V的值设置为N,若V的值和E不等,则说明该值已经被其他线程更新了,则当前线程可以选择重试或者放弃操作。

在DB中表中添加version字段来实现,select数据时也读取version,当更新数据的时候,判断version与DB中的是否相同,如果是,则正常更新且version+1;否则更新失败。

a.基于悲观锁
使用select * from table-1 where id = '10000' for update,id是主键。当这条记录添加上悲观锁后,其他线程无法操作该记录,执行完成后,释放锁即可。

3.1 基于Redis实现

依赖于Redis的原子操作。
加锁:

String result = redis.set(locked_key, request_random_Id, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expire_time);
if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
 return false;

释放锁:

 String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(request_random_Id));

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

释放锁的时候需要判断request_random_Id是否等于自己的,如果相等则删除
参考:https://www.cnblogs.com/linjiqin/p/8003838.html

3.1 基于Zookeeper实现

使用Zookeeper的临时节点来实现分布式锁。
原理就是:当一个clietn想要加锁时,就在zookeeper上的指定/lock节点的目录下,去生成一个唯一的临时有序节点, 然后判断自己是否是这些有序节点中序号最小的一个,如果是,则意味着获取了锁。如果不是,则说明没有获取到锁,那么就需要在序列中找到比自己小的那个节点,并对其调用 watch()方法,对其注册事件监听,当监听到这个节点被删除了, 再次争取锁,如果获取了锁,则执行自己的程序,然后删除临时节点,即删除锁;否则重复以上步奏,判断自己是否是最小节点。

上一篇 下一篇

猜你喜欢

热点阅读