首页 > 编程语言 > 详细

java - redis - incr and expire lua

时间:2020-09-27 13:56:01      阅读:126      评论:0      收藏:0      [点我收藏+]

使用原子自增和 expire 搭配实现原子操作

 @Bean(name = "customStringRedisTemplate")
    public RedisTemplate<String, String> customStringRedisTemplate(RedisConnectionFactory factory) {
// 要求使用默认序列化,否则有可能会抛出user_script:1: ERR value is not an integer or out of range 异常
        return new StringRedisTemplate(factory);
    }

    @Autowired
    private RedisTemplate<String, String> customStringRedisTemplate;

    @Test
    public void customLock() {
        String key = "cmq_im_dispatch_user_";
//        customStringRedisTemplate.delete(key);
        String incrByAndExpireLua = "if redis.call(‘incrBy‘, KEYS[1], ARGV[1]) == tonumber(ARGV[1]) then\n" +
                "    redis.call(‘expire‘, KEYS[1], ARGV[2])\n" +
                "    return tonumber(ARGV[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        if (!customStringRedisTemplate.hasKey(key)) {
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(incrByAndExpireLua, Long.class);
        // 要求这里输入的参数都需要为字符串 Long increment
= customStringRedisTemplate.execute(redisScript, Collections.singletonList(key), NumberUtils.INTEGER_ONE.toString(), "300"); // 即使在并发情况下也只允许一个线程进入 if (NumberUtils.LONG_ONE.equals(increment)) { try { log.info("{}线程进入", Thread.currentThread().getName()); } finally { customStringRedisTemplate.delete(key); } } } }

 

对于lua脚本的分析: 

  1. "redis.call(‘incrBy‘, KEYS[1], ARGV[1])" ,表示当前调用"incrBy"命令,并指定key为输入参数的第一个参数key,value为第一个参数value
  2. 由于"incrBy"会返回增加后的结果,如果当前key不存在,则会生成新的key,且默认value为0并增加输入的value; 因此对于判断 " == tonumber(ARGV[1])",这里要求"ARGV[1]"需要不等于0,否则无法判断是否是第一次操作
  3. 对于 "if option then operate else operate" ,就是简单的if else判断操作, 如果是第一次操作,则在调用expire命令设置过期时间,原因在于对于"incrBy"生成的新的key默认过期时间为 -1 表示永远存活;
  4. 对于return 操作表示当前操作会返回数据,对于返回数值类型数据操作,要求java必须使用Long类型接收;也可以直接返回布尔类型数据

 

java - redis - incr and expire lua

原文:https://www.cnblogs.com/xingguoblog/p/13738907.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!