在单机环境,我们使用最多的是juc包里的单机锁,但是随着微服务分布式项目的普及,juc里的锁是不能控制分布锁环境的线程安全的,因为单机锁只能控制同个进程里的线程安全,不能控制多节点的线程安全,所以就需要使用分布式锁
分布式锁的原理就不说太多了,主要讲讲基于redis的分布式锁的用法。
一、redis分布式锁原理
实际上不管在java中怎么实现redis锁,其实底层都是使用 redis的setnx
和expire 命令 来实现的。命令行操作如下:
setnx命令:
SETNX是SET if not exists的简写,设置key的值,如果key值不存在,则可以设置,否则不可以设置,这个有点像juc中cas锁的原理
# setnx命令,相当于set和nx命令一起用
setnx tkey aaa
EX : 设置指定的到期时间(以秒为单位)。
PX : 设置指定的到期时间(以毫秒为单
NX : 仅在键不存在时设置键。
XX : 只有在键已存在时才设置。
expire命令:
如果只使用setnx
不加上过期时间,手动释放锁时候出现异常,就会导致一直解不了锁,所以还是要加上expire
命令来设置过期时间。
- 保证原子性
但是又有一个问题,设置过期时间时候报错了,也同样会导致锁释放不了,所以为了保证原子性,需要这两个命令一起执行
# set tkey过期时间10秒,nx:如果键不存在时设置
set tkey aaa ex 10 nx
二、Jedis 实现分布式锁
简单实现
public static void main(String[] args) {for(int i = 0;i < 10 ;i++ ){Thread thread = new Thread(new Runnable() {@Overridepublic void run() {Boolean fuck = true;while (fuck) {//连接本地的 Redis 服务Jedis jedis = new Jedis("",6379,0);// 如果 Redis 服务设置了密码,需要用下面这行代码输入密码jedis.auth("");
// System.out.println("连接成功");
// //查看服务是否运行
// System.out.println("服务正在运行: "+jedis.ping());if (jedis.setnx("lock", "1") == 1) {// 获取锁成功jedis.expire("lock", 10); // 设置锁的过期时间System.out.println("2222222222222");fuck = false;}}}});thread.start();}