利用缓存redis作分布式架构服务锁的简单应用

13 篇文章 0 订阅
3 篇文章 0 订阅

1.项目架构说明

最近公司新项目上了很多新技术,如消息队列、微服务、集群、分库分表等,服务才分称多个微服务,关联模块放一起组成一个服务,每个服务还可能使多机的集群模式,通过一个统一的网关控制;

2.遇到的问题

微服务之间,机子集群直接就需要交互,并发竞争问题就不可避免,因为不是同一台机子,项目运行的时候,一个功能并不保证只请求一台机子,而是请求了多台机子,造成并发和竞争的问题;

3.引入分布锁

对于当前的问题,经过会议讨论,得出两个解决方案,一是使用消息队列有序读取,多机按取余序处理;二是使用缓存的分布锁,公司最近用redis,所以就决定用redis作分布锁;因此,对于redis分布锁,简单应用也有两个方式,如下:

1)使用setnx key value

这个方式存在死锁的弊端,因此在操作是需要一些操作,setnx 命令设置值时,返回1为成功,0为已有数据,因此可以key 不变,value 为时间戳,然后在每次setnx 返回0 后,去判断时间戳的超时问题(超时值自己设定),未超时不动作(没有获得锁),超时再用getset key value ,将新的时间戳设置进去,获取旧值判断是否超时(再一次判断),未超时不动作(没得锁),超时了即获得锁;
方式1)的方式仍有弊端,就是分布式多服务间,多台机子直接时间的统一性问题,如果一台机子系统时间比其他机子时间要晚(超过超时时间值),那这台机子将永远获得锁,因此方式2)可以规避这个问题;

2)使用 set key value ex|px nx

这个方式ex 为秒, px 为毫秒,首先设置值时返回ok成功,再设置同样的key值时返回空,返回成功视为获得锁,返回空视为未获得锁,时间统一以redis 内部时间,因此可作为分布锁,消除死锁,也避免多服务系统时间不统一的问题;

代码例子:

/**
     * 不存在时插入 ,可用做分布锁
     * 
     * @param key
     * @param value
     * @param time
     * @param unit
     * @return
     */
    public static boolean setNx(String key, Object value, long time, TimeUnit unit) {
    	Boolean flag = REDIS_TEMPLATE.opsForValue().setIfAbsent(key, JSONObject.toJSONString(value), time, unit);
    	if(flag == null || !flag) {
    		return false;
    	}else {
    		return true;
    	}
    }

技术交流QQ群-595892258

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Retank

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值