实现原理
分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。
为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。
使用Redis实现锁的原因
- Redis有很高的性能;
- Redis命令对此支持较好,实现起来比较方便。
主要利用到的命令
SETNX
SETNX key val
当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。
expire
expire key timeout
为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
delete
delete key
删除key
实现思想
- 获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,保证key一致,通过此在释放锁的时候进行判断。
- 获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
- 释放锁的时候,当前时间小于超时时间,则执行delete进行锁释放。
代码结构
1 | package com.devframe.util; |
配置
1 | # redis lock |
测试
测试就选用最经典的秒杀系统吧,使用分布式锁可以控制资源。
下面模拟500人秒杀100件商品。
1 | package com.devframe.util; |
不加锁的部分结果:
1 | Thread-100获取了锁 |
上锁的结果:
1 | Thread-8获取了锁 |
总结
- 并发量大的时候,需要考虑锁时间;
- 考虑失败情况,上锁了,但是设置超时时间失败(redis崩溃等各种情况),锁一致都没有释放,导致死锁的情况发生,现在需要做的是,把key的value设置成超时的时间,每次上锁失败都去检查一次,超时的就覆盖,可以避免死锁。