标签:tps 绑定 死锁 组织 代码 访问共享 没有 ali 特殊
前面学习了Redis的数据结构以及命令、Redis中的事务和Redis对Lua脚本的支持。
这一章就对Redis这些特性做一下实战性应用——基于Redis的分布式锁实现。
在这之前先来认识下锁(Lock)和分布式锁(Distributed Lock):
In computer science, a lock or mutex (from mutual exclusion) is a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution. A lock is designed to enforce a mutual exclusion concurrency control policy.
参考wiki的解释:在计算机科学领域中,锁是为了限制多线程环境访问一个资源的一种同步机制。锁被设计相互排斥的并发策略。
Lock的前提条件:
Lock目标:
Lock的实现:
Operating systems use lock managers to organise and serialise the access to resources. A distributed lock manager (DLM) runs in every machine in a cluster, with an identical copy of a cluster-wide lock database. In this way a DLM provides software applications which are distributed across a cluster on multiple machines with a means to synchronize their accesses to shared resources.
参考wiki解释分布式锁:操作系统用锁管理器实现有组织有顺序的访问资源。分布式锁运行在集群环境中的每台机器上,使得数据具有相同的副本。分布式锁提供分布式软件应用同步访问共享资源。
Distribute Lock的前提条件:
Distribute Lock目标:
Distribute Lock实现方式:
按照用途、场景划分,锁的类型非常多。如:排它锁(独占式锁)、共享锁,自旋锁、互斥锁,读锁、写锁。但是在分布式环境中的所谓的分布式锁,大多数情况下都是指:分布式独占式锁。
1.特点分析:
本质:同步互斥,使得处理任务能够一个一个逐步的过临界资源。
造成的影响:
本质:使得吞吐量大打折扣。
1.Redis本身就是单线程:
2.Redis提供了set if not exists操作:
下面来先来看下获取锁:
return jedis.set(lockKey, lockValue, NX, EX, expireTime) != null ? true : false;
这里使用set指令,具有原子操作特点,不会被其他客户端操作中断,在分布式环境中,是安全的,没有竞态条件产生,一次只能有一个客户端争用锁;使用nx,即存在不设置,符合独占特点;设置ex,有过期效果,不会产生永久独占即死锁;最后设置了lockValue,这样就和当前加锁任务做了绑定,后面可以用其作为解锁的钥匙;
再来看下解锁操作:
static final String RELEASE_LOCK_LUA = "if redis.call(‘get‘, KEYS[1]) == ARGV[1] " +
"then return redis.call(‘del‘, KEYS[1]) else return 0 end";
Object result = jedis.eval(RELEASE_LOCK_LUA, 1, lockKey, lockValue);
这里解锁是用了Lua脚本,上篇文章中介绍了Redis内置一个Lua解释器,Redis调用解释器执行Lua脚本也是具有原子性的,即同一时刻只有一个客户端的操作能被执行,所以这里使用Lua脚本解锁无竞态条件;解锁符合是占用锁的任务释放的原理;
但是以上实现的分布式锁缺点是:
本人对其进行了改造,分别做了适应以上两种场景的分布式锁,详情可以戮[Distributed Lock],欢迎大家一起来完善。
本文从What、Features、How的角度分析了分布式锁。总的来说,单机应用中的多线程或者多进程的锁的放大版基本上就是分布式锁了。万变不离其宗,实现独占锁的关键性要素:
Redis 分布式锁的正确实现方式
Rewriting our lock
Lock
参考Rewriting our lock中使用setnx实现的分布式,严格意义上来说是有死锁问题的。setnx和expire不具有原子性。当setnx成功后,expire前应用发生宕机,这会导致锁永远不会过期,别的应用始终争用不到锁。当然这种情况比较特殊,但是做代码是一件严谨的事!
标签:tps 绑定 死锁 组织 代码 访问共享 没有 ali 特殊
原文地址:https://www.cnblogs.com/lxyit/p/9829132.html