Redis分布式锁

更新日期: 2019-05-04 阅读: 4k 标签: 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<>();

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/3194

相关推荐

Redis可视化管理工具有哪些?

redis 是当前非常流行的缓存数据库,得益于其简单的 key-value 模式的数据存储和丰富的数据类型与事件机制使得 redis 成为当前后端开发中不可或缺的利器。下面推荐一些好用的 redis 的管理工具

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

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

在使用redis-cluster之前你需要知道这些事

前段时间基础架构组、DBA还有云盘团队一起推广了phpredis的RedisCluster的线上使用,目前线上业务已经稳定,单业务的规模水平是:Qps平均15W,数据量在700G左右。现对这段时间的工作和所遇到的一些常见问题进行简单总结

基于redis实现定时任务

业务中碰到的需求(抽象描述一下):针对不同的用户能够实现不同时间的间隔循环任务。比如在用户注册成功24小时后给用户推送相关短信等类似需求。使用crontab?太重,且基本不现实,不可能给每一个用户在服务器上生成一个定时任务。

docker搭建redis集群

从docker库获取ruby镜像;创建虚拟网卡;查看网卡信息;查看redis-net虚拟网卡网关ip;创建需要挂载的目录以及文件;在/docker/redis目录下创建一个sh脚本文件;执行脚本创建挂载目录以及配置文件

redis用在哪里?redis 应用场景

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

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

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

Redis中设置了过期时间的Key,那么你还要知道些什么?

熟悉Redis的同学应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除。这就是Redis的过期策略。在为key设置过期时间需要注意的事项

Redis 的各项功能解决了哪些问题?

官方简介解释到:Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存中的一个存储系统,你可以把它作为数据库,缓存和消息中间件来使用。同时支持strings,lists,hashes,sets,sorted sets

Redis面试常问的知识点总汇

Redis 是一个基于内存的高性能key-value数据库。Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。

点击更多...

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