• 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为第二步生成值

  • 相关阅读:
    Cygwin配置总结
    javap 指令集
    超好用的Vim配置
    超过 130 个你需要了解的 vim 命令
    21、面向对象
    20、MySQLdb
    深入java字符串原理及其效率分析
    数据库执行计划
    SQL中EXISTS的用法
    mybatis之foreach用法
  • 原文地址:https://www.cnblogs.com/alan319/p/10600641.html
Copyright © 2020-2023  润新知