在實際的業務場景中,我們會用到流水號。
之前的流水號做法是,使用redis的全局鎖。然後對數據庫進行更新,數據庫更新 這個也會有一些問題,比如對於同一個流水號,多個線程去更新,由於事務比較長,那麼就會導致數據庫被鎖定。
這個可以使用redis的lua 腳本去解決。
由於redis 是單線程的處理模式,因此執行 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 爲參數,list爲參數傳入,這裏需要保證數據的類型和redis 的函數保持一致。
另外我們需要保證redis 的存儲。
我們可以使用AOF模式
點擊查看代碼
//啓動AOf
appendonly yes
//每秒同步
appendfsync everysec