承接国内外服务器租用托管、定制开发、网站代运营、网站seo优化托管接单、网站代更新,新老站点皆可!!咨询QQ:3787320601

怎么操作Redis和zookeeper实现散布式锁

管理员 2023-06-24 07:48:38 互联网圈 16 ℃ 0 评论 5262字 收藏

怎么操作Redis和zookeeper实现散布式锁

怎么操作Redis和zookeeper实现散布式锁

在散布式场景下,有很多种情况都需要实现终究一致性。在设计远程上下文的领域事件的时候,为了保证终究一致性,在通过领域事件进行通讯的方式中,可以同享存储(领域模型和消息的持久化数据源),或做全局XA事务(两阶段提交,数据源可分开),也能够借助消息中间件(消费者处理需要能幂等)。通过Observer模式来发布领域事件可以提供很好的高并发性能,并且事件存储也能追溯更小粒度的事件数据,使各个利用系统具有更好的自治性。

1.散布式锁

散布式锁一般用在散布式系统或多个利用中,用来控制同一任务会不会履行或任务的履行顺序。在项目中,部署了多个tomcat利用,在履行定时任务时就会遇到同一任务可能履行屡次的情况,我们可以借助散布式锁,保证在同一时间只有一个tomcat利用履行了定时任务。

2.散布式锁的实现方式

  • 使用redis的setnx()和expire()
  • 使用redis的getset()
  • 使用zookeeper的创建节点node
  • 使用zookeeper的创建临时序列节点

3.使用redis的setnx()和expire()来实现散布式锁

setnx(key,value) 如果key不存在,设置为当前key的值为value;如果key存在,直接返回。
expire()来设置超时时间

定义注解类:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Lockable{
// redis缓存key
String key();
// redis缓存key中的数据
String value() default “”;
// 过期时间(秒),默许为一分钟
long expire() default 60;
}

定时任务增加注解@Lockable:

@Lockable(key = “DistributedLock:dealExpireRecords”)
public void dealExpireRecords() {
}

定义一个aop切面LockAspect,使用@Around处理所有注解为@Lockable的方法,通过连接点确认此注解是用在方法上,通过方法获得注解信息,使用setIfAbsent来判断会不会获得散布式锁,如果没有获得散布式锁,直接返回;如果获得到散布式锁,通过expire设置过期时间,并调用指定方法。

@Component
@Slf4j
@Aspect
public class LockAspect {

@Autowired
private RedisTemplate redisTemplate;

@Around(“@annotation(com.records.aop.Lockable)”)
public Object distributeLock(ProceedingJoinPoint pjp) {
Object resultObject = null;

//确认此注解是用在方法上
Signature signature = pjp.getSignature();
if (!(signature instanceof MethodSignature)) {
log.error(“Lockable is method annotation!”);
return resultObject;
}

MethodSignature methodSignature = (MethodSignature) signature;
Method targetMethod = methodSignature.getMethod();

//获得注解信息
Lockable lockable = targetMethod.getAnnotation(Lockable.class);
String key = lockable.key();
String value = lockable.value();
long expire = lockable.expire();

// 散布式锁,如果没有此key,设置此值并返回true;如果有此key,则返回false
boolean result = redisTemplate.boundValueOps(key).setIfAbsent(value);
if (!result) {
//其他程序已获得散布式锁
return resultObject;
}

//设置过期时间,默许一分钟
redisTemplate.boundValueOps(key).expire(expire, TimeUnit.SECONDS);

try {
resultObject = pjp.proceed(); //调用对应方法履行
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return resultObject;
}
}

4.使用redis的getset()来实现散布式锁

此方法使redisTemplate.boundValueOps(key).getAndSet(value)的方法,如果返回空,表示获得了散布式锁;如果返回不为空,表示散布式锁已被其他程序占用

5.使用zookeeper的创建节点node

使用zookeeper创建节点node,如果创建节点成功,表示获得了此散布式锁;如果创建节点失败,表示此散布式锁已被其他程序占用(多个程序同时创建一个节点node,只有一个能够创建成功)

6.使用zookeeper的创建临时序列节点

使用zookeeper创建临时序列节点来实现散布式锁,适用于顺序履行的程序,大体思路就是创建临时序列节点,找出最小的序列节点,获得散布式锁,程序履行完成以后此序列节点消失,通过watch来监控节点的变化,从剩下的节点的找到最小的序列节点,获得散布式锁,履行相应处理,顺次类推……

感谢浏览,希望能帮助到大家,谢谢大家对本站的支持!

文章来源:丸子建站

文章标题:怎么操作Redis和zookeeper实现散布式锁

https://www.wanzijz.com/view/58820.html

X

截屏,微信识别二维码

微信号:weimawl

(点击微信号复制,添加好友)

打开微信