关闭

Redis分布式锁

时间: 2019-05-04阅读: 1537标签: redis

redis:Redis是开源,内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理.采用单进程单线程模型,并发能力强大,主流的分布式缓存工具


加锁

通过setnx向特定的key值写入一个随机值,并且同时设置失效时间,写值成功即加锁成功.

注意点

  • 1.必须给锁加一个失效时间,避免死锁.
  • 2.加锁时,每个节点产生一个随机字符串,避免误删锁.

比如:A节点加锁并设置有效时间,A未执行完毕但是锁已经失效了,B节点趁机加锁,此时A节点准备执行解锁动作,若AB节点加锁写入的值相等的话会造成A节点去解锁B节点的锁,显然不行.

  • 3.写入随机值与设置有效时间必须同时的,是原子操作,防止未设置有效时间.setnx命令

maven依赖:

<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>1.7.3.RELEASE</version>
</dependency>
<dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
</dependency>


解锁

匹配随机值,删除redis上的特定key的数据,要保证删除动作是原子的,即获取数据丶判断一致丶及删除数据三个操作是原子的。执行如下lua脚本:
ARV[1]是value值

if redis.call("get",KEYS[1])==ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end

lua脚本丢到服务器上,它认为是一个操作序列不可分开的序列,redis介绍时说过是一个单进程单线程模型,这点要牢牢记住,因此会通过一个线程执行这个脚本之后才会去处理别的请求,因此保证了lua脚本保证了原子性.

代码实现:
加锁:

public boolean tryLock() {
    //随机生成字符串
    String uuid= UUID.randomUUID().toString();
    //获取redis原始链接
    Jedis jedis = redisManager.getJedis();
    //使用setnx命令请求写值,并设置有效时间
    String ret=jedis.set(KEY,uuid,"NX","PX",1000);
    if("OK".equals(ret)){
        //供给unlock时从threadLocal获取此值,ThreadLocal完成数据共享
        local.set(uuid);
        return  true;
    }
    return false;
}

解锁:

public void unlock() {
        //读取lua脚本
        String script= FileUtils.readFileByLines("lua脚本路径");
        Jedis jedis=redisManager.getJedis();
         //链接redis执行Lua脚本,value值无法从unlock方法入参了,因此用threadLocal来获取
        jedis.eval(script, Arrays.asList(KEY),Arrays.asList(local.get())); 
}    

这里是简单的代码实现具体讲怎么用jedis执行对应的方法,方法不齐的可以自行查阅资料

顺便简单讲下ThreadLoacl
//1/做线程级的数据传递,在spring.mybatis随处可见
//2.比如spring的事务传播属性就是通过threadLocal来传递的
//3.tomcat的session也是放在threadLocal的
private static ThreadLocal<String> local = new ThreadLocal<>();
站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/3194

关闭

分布式锁的redis缓存使用方式

目前有很多成熟的缓存产品,包括Redis,memcached等。这里以Redis为例来分析下使用缓存实现分布式锁的方案。主要的实现方式是使用Jedis.setNX方法来实现。以上实现方式同样存在几个问题:

PHP使用redis防止大并发下二次写入

php调用redis进去读写操作,大并发下会出现:读取key1,没有内容则写入内容,但是大并发下会出现同时多个php进程写入的情况,这个时候需要加一个锁,即获取锁的php进程有权限写。

Redis的基本数据结构及基本命令详解

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)

使用 Redis 构建先进先出队列解决秒杀问题

先进先出队列(first in first out queue)是一种非常常见的数据结构, 一般都会包含入队(enqueue)和出队(dequeue)这两个操作, 其中入队操作会将一个元素放入到队列中, 而出队操作则会从队列中移除最先被入队的元素

Redis不仅仅是缓存,还是……

一段时间以来,巨大数量的数据处理迫使所有的应用程序在数据库层前添加缓存策略。即使经典数据库进行了大量的下划线优化,仍然不能提供足够的速度和可用性。主要原因在于数据存储越远,获取数据就越困难

node怎么用redis怎么做消息队列?

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。

Redis为什么变慢了?

Redis作为内存数据库,拥有非常高的性能,单个实例的QPS能够达到10W左右。但我们在使用Redis时,经常时不时会出现访问延迟很大的情况,如果你不知道Redis的内部实现原理,在排查问题时就会一头雾水。

Redis 中 Lua 脚本的应用和实践

前段时间组内有个投票的产品,上线前考虑欠缺,导致被刷票严重。后来,通过研究,发现可以通过 redis lua 脚本实现限流,这里将 redis lua 脚本相关的知识分享出来,讲的不到位的地方还望斧正。

redis用在哪里?redis 应用场景

Redis是一个由Salvatore Sanfilippo写的key-value存储系统。Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

PHP操作Redis常用技巧总结

Redis连接与认证连接参数:ip、端口、连接超时时间,连接成功返回true,否则返回false,设置键值:成功返回true,否则返回false,获取键值:成功返回String类型键值

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!