java+redis+lua生成自動增長的ID序列號


1.編寫lua腳本用於生成主鍵ID序列號,內容如下

local key = tostring(KEYS[1]);
local count = tonumber(KEYS[2]);
local dateStr = tostring(KEYS[3]);

local newKey = key .. "_" .. dateStr;
local numRedis = redis.call("incr", newKey);
print(numRedis);

if (numRedis == 1) then
	redis.call("expire",newKey,60);
end

-- 計算數字的位數
local function DightNum(num)
	if math.floor(num) ~= num or num < 0 then
		return -1;
	elseif 0 == num then
		return 1;
	else
		local tmp_dight = 0;
		while num > 0 do
			num = math.floor(num/10);
			tmp_dight = tmp_dight + 1;
		end
		return tmp_dight;
	end
end

-- 在整數數字前面加0
-- dest_dight 標識最終生成位數,例如 AddZeroFrontNum(5, 1) 計算后是00001
local function AddZeroFrontNum(dest_dight, num)
	local num_dight = DightNum(num);
	if -1 == num_dight then
		return -1;
	elseif dest_dight <= num_dight then
		return tostring(num);
	else
		local str_e = ""
		for var =1, dest_dight - num_dight do
			str_e = str_e .. "0";
		end
		return str_e .. tostring(num);
	end
end

local idStr = AddZeroFrontNum(count, numRedis);
return dateStr .. idStr;

2.redis加載lua腳本文件

redis-cli -a redis script load "$(cat getGenerateId.lua)"
"b3d58fe8b47b1ca1e1fb074db5c3506a09ffdae8"

-a: redis密碼,如果沒有密碼,該項不需要輸入
下面的字符串即為加載后redis保存的sha值,通過該sha值可以訪問lua腳本

3.java代碼執行緩存的lua腳本文件

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
@Service
public class RedisService {

    private static final DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public Object executeScript(final String sha, final List<String> keys, final ArrayList<String> vals) {
        return redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                Jedis jedis = (Jedis) connection.getNativeConnection();
                return jedis.evalsha(sha, keys, vals);
            }
        }, true);
    }

    /**
     * 每秒從 1 開始生成唯一標識,包括時間戳:yyyyMMddHHmmss
     * 最終格式為:yyyyMMddHHmmss + 四位有序數字
     * @param sha     redis中生成lua腳本的序列號
     * @param key     redis中存放id的key前綴
     * @param length  后面生成有序數字的位數
     * @return
     */
    public Long fetchUUID(String sha, String key, String length){
        List<String> keys = new ArrayList<>();
        keys.add(key);
        keys.add(length);
        Calendar now = new GregorianCalendar();
        String datetime = df.format(now.getTime());
        keys.add(datetime);
        Object obj = executeScript(sha, keys, new ArrayList<String>());
        return Long.parseLong(String.valueOf(obj));
    }
}

然后調用fetchUUID該方法就可以了,key和length自定義,sha為第二步生成值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM