首页 / REDIS / 基于单节点redis实现分布式锁
基于单节点redis实现分布式锁
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了基于单节点redis实现分布式锁,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3241字,纯文字阅读大概需要5分钟。
内容图文
![基于单节点redis实现分布式锁](/upload/InfoBanner/zyjiaocheng/864/90c32a1097fa414b81eae3435ff81d47.jpg)
使用redis实现分布式锁基本就2步:第一多线程请求处理获取锁时,使用setnx指令,只有当key不存在时才设值,注意设置超时时间。
set key value [expiration EX seconds|PX milliseconds] [NX|XX]
第二相关业务处理完成之后,谁加的锁应该由谁去及时释放,即删除指定的key,注意删除时要匹配加锁线程的value,避免因超时误删其它线程的锁,这里使用Lua脚本执行原子操作,也可以先判断key value再del。
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
----
下面使用单节点redis,redis版本5.0.8,版本客户端使用jedis3.2.0,完成相关加锁,释放锁的操作。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
注意使用jedisPool时默认最大连接数是8,使用完记得关闭连接,否则会造成线程等待,set成功时返回"OK",lua脚本删除成功时,返回"1"。
public boolean lock(String key, String value, long waitTimeOut, SetParams params) {
Jedis jedis = null;
try {
jedis = JedisPool.getResource();
long
? ? ? ?for (; ; ) {
? ? ? ? ? ?String lock = jedis.set(key, value, params);
? ? ? ? ? ?if ("OK".equals(lock)) {
? ? ? ? ? ? ? ?return true;
? ? ? ? ? ?}
? ? ? ? ? ?long wait = System.currentTimeMillis() - start;
? ? ? ? ? ?if (wait >= waitTimeOut) {
? ? ? ? ? ? ? ?return false;
? ? ? ? ? ?}
? ? ? ? ? ?try {
? ? ? ? ? ? ? ?Thread.sleep(100);
? ? ? ? ? ?} catch (InterruptedException e) {
? ? ? ? ? ? ? ?log.error("");
? ? ? ? ? ? ? ?return false;
? ? ? ? ? ?}
? ? ? ?}
? ?} catch (Exception e) {
? ? ? ?e.printStackTrace();
? ? ? ?return false;
? ?} finally {
? ? ? ?jedis.close();
? ?}
}
public boolean unlock(String key, String value) {
? ?Jedis jedis = null;
? ?try {
? ? ? ?jedis = JedisPool.getResource();
? ? ? ?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(key),
? ? ? ? ? ? ? ?Collections.singletonList(value));
? ? ? ?if ("1".equals(result.toString())) {
? ? ? ? ? ?return true;
? ? ? ?}
? ? ? ?return false;
? ?} catch (Exception e) {
? ? ? ?e.printStackTrace();
? ? ? ?return false;
? ?} finally {
? ? ? ?jedis.close();
? ?}
}
----
最后,在controller里简单测试一下锁的效果:
@GetMapping("hello")
public String hello() {
String value = System.nanoTime() + "." + UUID.randomUUID();
CountDownLatch latch = new CountDownLatch(1000);
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
redisLock.lock(KEY,value,1000,SetParams.setParams().nx().px(500000));
amount--;
System.out.println(Thread.currentThread() + ":" + amount);
redisLock.unlock(KEY,value);
latch.countDown();
}).start();
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return "amount:" + amount;
}
不加锁时多次执行会出现数据错误,添加锁后数据正常,可以使用专业的工具进行测试验证,这里为了等待所有线程执行完成使用了countDownLatch。
----
这里的分布式锁是基于redis单点完成的,使用单机可能会出现单节点故障。且锁是不可重入的。通常redis都是集群部署的,可以使用redission来完成集群redis的分布式锁操作,实现了redlock算法,且value关联线程,实现了锁的可重入。
内容总结
以上是互联网集市为您收集整理的基于单节点redis实现分布式锁全部内容,希望文章能够帮你解决基于单节点redis实现分布式锁所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。