如何操作Redis和zookeeper实现分布式锁

 更新时间:2017年07月10日 14:28:37   作者:htlr的博客  
这篇文章主要介绍了如何操作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来监控节点的变化,从剩下的节点的找到最小的序列节点,获取分布式锁,执行相应处理,依次类推......

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

相关文章

  • 分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了

    分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了

    Zookeeper的机制可以保证分布式锁实现业务代码简单,成本低,Redis如果要解决分布式锁的问题,对于一些复杂的情况,很难解决,成本较高,这篇文章重点给大家介绍分布式锁选择Zookeeper 而不是Redis的理由,一起看看吧
    2021-05-05
  • redis中RDB(Redis Data Base)的机制

    redis中RDB(Redis Data Base)的机制

    本文主要介绍了redis中RDB(Redis Data Base)的机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Redis内存回收策略

    Redis内存回收策略

    这篇文章主要介绍了Redis内存回收策略,需要的朋友可以参考下
    2007-02-02
  • Redis的数据存储及String类型的实现

    Redis的数据存储及String类型的实现

    这篇文章主要介绍了Redis的数据存储及String类型的实现,redis作为k-v数据存储,因查找和操作的时间复杂度都是O(1)和丰富的数据类型及数据结构的优化,了解了这些数据类型和结构更有利于我们平时对于redis的使用,需要的朋友可以参考下
    2022-10-10
  • Win10下 Redis启动 错误1067导致进程意外终止的解决方法

    Win10下 Redis启动 错误1067导致进程意外终止的解决方法

    这篇文章主要介绍了Win10下 Redis启动 错误1067导致进程意外终止的完美解决方案,需要的朋友可以参考下
    2018-01-01
  • redis实现sentinel哨兵架构的方法

    redis实现sentinel哨兵架构的方法

    哨兵是一个分布式系统,可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossip protocols)来接收关于Master主服务器是否下线的信息,这篇文章主要介绍了redis实现sentinel哨兵架构,需要的朋友可以参考下
    2022-11-11
  • Redis RDB与AOF持久化方式详细讲解

    Redis RDB与AOF持久化方式详细讲解

    Redis是基于内存的数据结构服务器,保存了大量的键值对数据,所以持久化到磁盘是非常必要的,Redis提供了两种持久化的方式,分别是RDB和AOF。下面我们看下这两种持久化方式的具体实现原理
    2022-11-11
  • IDEA初次连接Redis配置的实现

    IDEA初次连接Redis配置的实现

    本文主要介绍了IDEA初次连接Redis配置的实现,文中通过图文步骤介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-12-12
  • Redis分布式锁解决秒杀超卖问题

    Redis分布式锁解决秒杀超卖问题

    本文主要介绍了Redis分布式锁解决秒杀超卖问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 分布式爬虫处理Redis里的数据操作步骤

    分布式爬虫处理Redis里的数据操作步骤

    这篇文章主要介绍了分布式爬虫处理Redis里的数据操作步骤,数据分别存入mongodb和mysql数据库,具体内容详情及实例代码大家参考下本文
    2018-03-03

最新评论