暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

冗余双写分布式可重入锁解决方案

219

需求介绍

    在短链服务中,由于引入了消息队列采取的是冗余双写的解决方案,那么如何才能保证用户A的数据同时在B端消费者和C端消费者都是 先成功插入的呢?


解决方案介绍

     1、redis作为分布式锁

     2、key代表的是短链码code

     3、value代表的是用户账号id



踩过的坑

    在消费者端的业务代码和生产者端的业务代码不是同一个线程中的操作,即如果引入了消息队列以后,消费者和生产者是相互独立的, 生产者和消费者唯一的联系就是通过传递的消息来关联,因此生产者端存放在线程中的ThreadLocal中的内容必须显示取出来通过 消息传递给消费者端。


伪代码实现

    @Override
    public boolean handleAddShortLink(EventMessage eventMessage) {
    // 验证合法性操作 TODO
    String code = shortLinkComponent.createShortLinkCode(shortLinkAddRequest.getOriginalUrl());
    //加锁
    //key1是短链码,ARGV[1]是accountNo,ARGV[2]是过期时间
    String script = "if redis.call('EXISTS',KEYS[1])==0 then redis.call('set',KEYS[1],ARGV[1]); redis.call('expire',KEYS[1],ARGV[2]); return 1;" +
    " elseif redis.call('get',KEYS[1]) == ARGV[1] then return 2;" +
    " else return 0; end;";


    Long result = redisTemplate.execute(new
    DefaultRedisScript<>(script, Long.class), Arrays.asList(code), eventMessage.getAccountNo(),100);
    log.info("分布式锁加锁后的result={}",result);
    //result!=0表示加锁成功
    if(result!=0){
    if(EventMessageType.EVENT_LINK.name().equalsIgnoreCase(messageType)){
    //查询C端数据库中是否已经存在该短链码
    ShortLinkDO linkCode = shortLinkManager.findByShortLinkCode(code);
    if(linkCode==null){
    log.info("C端不存在这个短链对象,可以插入");
    //构造短链对象 C端对象 TODO
    //将短链对象插入数据库
    shortLinkManager.addShrotLink(shortLinkDO);
    return true;
    }
    return false;
    }else if(EventMessageType.EVENT_MAPPING.name().equalsIgnoreCase(messageType)){
    //查询B端数据库中是否已经存在该短链码
    GroupCodeMappingDO groupCodeMappingDO = mappingManager.findByCode(code,shortLinkAddRequest.getGroupId(),eventMessage.getAccountNo());
    if(groupCodeMappingDO==null){
    log.info("B端不存在这个短链对象,可以插入");
    //构造短链对象 B端对象 TODO
    //将短链插入数据
    mappingManager.add(mappingDO);
    return true;
    }
    return false;
    }
    }
    return false;
    }



    文章转载自梁霖编程工具库,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论