1.概要

之前的流水号实现是使用的 redis分布式锁,加数据递增的方式实现的。这种方式有什么问题呢。
分布式锁,对于在系统竞争激烈的情况下,会导致系统串行执行。另外本身数据库执行的效率也不高。

2.解决办法

redis 是一个单线执行的缓存服务。因此我们可以使用 redis 执行 lua 脚本。执行lua 脚本的时候,由于是单线程的,那么使用脚本并发的安全性是可以保证的。

下面就是相关的代码:

private Long getNo(String key,Integer initVal,Short step,Integer timeout){
        DefaultRedisScript<Long> redisScript= new DefaultRedisScript<>();

        //setex (key,timeout,val)
        String script="if(redis.call('exists',KEYS[1])==0) then  redis.call('setex',KEYS[1], tonumber(KEYS[4]), tonumber(KEYS[2]))  else redis.call('incrby',KEYS[1],tonumber(KEYS[3])) end  return tonumber(redis.call('get',KEYS[1]))";

        redisScript.setScriptText(script);

        List list=new ArrayList<>();
        //键
        list.add(key);
        //初始值
        list.add(initVal.toString());
        //步长
        list.add(step.toString());
        //超时时间
        list.add(timeout.toString());

        redisScript.setResultType(Long.class);

        Long rtn=(Long) redisTemplate.execute(redisScript,list);

        return rtn;
    }

其中 脚本中的KEYS ,表示为系统的参数。
lua 脚本的下标,是从1 开始的。

3. RESIS需要配置持久化

另外我们需要保证redis 的存储。

我们可以使用AOF模式

修改redis配置文件

//启动AOf
appendonly yes
//每秒同步
appendfsync everysec
文档更新时间: 2022-06-04 17:57   作者:zyg