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为第二步生成值
java+redis+lua生成自动增长的ID序列号的更多相关文章
- SQL获取刚插入的记录的自动增长列ID的值
		假设表结构如下: CREATE TABLE TestTable ( id int identity, CreatedDate datetime ) SQL2005获得新增行的自动增长列的语句如下: i ... 
- 使用强类型DataSet增加数据并获取自动增长的ID
		使用强类型的DataSet可以方便的操作数据库:有时候我们会对表的ID设置为自动增长,并且需要在插入数据后获取新插入数据的ID,按以下方法即可达到目的: 一. 首先建立一个表,id为自动增加, ... 
- 使用JDBC获取SQL自动增长的ID
		在项目开发中,遇到一个问题,先添加一条记录然后想立刻获取这条记录的ID值,ID由SQLServer自动增长的,如果先插入再查询的话,需要另外执行一条查询ID的SQL语句,因此有了下面的方法: 1.使用 ... 
- sql server生成自动增长的字母数字字符串
		在开发的过程中,我们经常会遇到要生成一些固定格式字符串,例如“BX201903150001”,结构为:BX+日期+N位序号,类似这种的字符串我们很难生成,在这里我们借助一个存储过程来实现这个功能. 1 ... 
- 写出一条Sql语句:取出表A中第31到第40记录(SQLServer,以自动增长的ID作为主键,注意:ID可能不是连续的。
		答:解1: select top 10 * from A where id not in (select top 30 id from A) 解2: select top 10 * from A ... 
- 写出一条Sql语句:取出表Customer中第31到第40记录(SQLServer,以自动增长的Id作为主键,注意:Id可能不是连续的。
		select top 10 * from (select ROW_NUMBER() over(order by Id) as rows,* from Customer) as C where C.ro ... 
- oracle 12c之前用sequence 和 trigger来生成自动增长的列
		SQL> create table scott.t1 (id number, val varchar2(8)); Table created. SQL> CREATE SEQUENCE s ... 
- java项目实现流水号自动增长
		项目中有一个规则编号字段,从1开始,编号长度为5位,那么第一条数据编号就是00001. 实现的基本思路就是项目启动时,从数据库获取当前最大值,作为静态变量存储: 业务获取新的编码,考虑并发问题,获取编 ... 
- spring boot:redis+lua实现顺序自增的唯一id发号器(spring boot 2.3.1)
		一,为什么需要生成唯一id(发号器)? 1,在分布式和微服务系统中, 生成唯一id相对困难, 常用的方式: uuid不具备可读性,作为主键存储时性能也不够好, mysql的主键,在分库时使用不够方便, ... 
随机推荐
- Spring JdbcTemplate详解
			为了使 JDBC 更加易于使用,Spring 在 JDBCAPI 上定义了一个抽象层, 以此建立一个JDBC存取框架. 作为 SpringJDBC 框架的核心, JDBC 模板的设计目的是为不同类型的 ... 
- ABP学习入门系列(三) (领域层中的仓储Repository)
			一,仓储定义:“在领域层和数据映射层的中介,使用类似集合的接口来存取领域对象”(Martin Fowler) . 仓储用来操作数据库进行数据存取.仓储接口在领域层定义,而仓储的实现类应该写在基础设施层 ... 
- mvc手把手教你写excel导入
			实习狗的每天新知识日常 准备工作: 1.在项目中添加对NPOI的引用,NPOI下载地址:http://npoi.codeplex.com/releases/view/38113 2.NPOI学习系列教 ... 
- int类型转换byte类型
			计算机中,int类型占用4个字节,byte类型占用1个字节: 当int类型强转为byte类型时,计算机会截取最后的八位(1个字节): 由于计算机存储数据时,都是以补码的形式进行存储. 然而,我们通常看 ... 
- Glide填坑指南
			一.前言:再优秀的开源库都有坑要填 手上的项目使用的图片加载框架是:Universal-Image-Loader+业务需要定制化的一些代码.Universal-Image-Loader 这个框架是一个 ... 
- K:Treap(堆树)
			Treap=Tree+Heap.Treap是一棵二叉排序树,它的左子树和右子树分别是一个Treap,和一般的二叉排序树不同的是, Treap记录一个额外的数据, 就是优先级.Treap在以关键码构 ... 
- K:跳表
			跳表(SkipList)是一种随机化的数据结构,目前在redis和leveldb中都有用到它,它的效率和红黑树以及 AVL 树不相上下,但跳表的原理相当简单,只要你能熟练操作链表, 就能轻松实现一 ... 
- 应用程序框架(一):DDD分层架构:领域实体(基础篇)
			一.什么是实体 由标识来区分的对象称为实体. 实体的定义隐藏了几个信息: 两个实体对象,只要它们的标识属性值相等,哪怕标识属性以外的所有属性值都不相等,这两个对象也认为是同一个实体,这意味着两个对象是 ... 
- Spring Boot—17MongoDB
			在MongoDB中插入如下的数据 db.baike.insert( { _id: 'freemark', desc: '新一代模板语言', tag: [ 'IT', '模板语言' ], comment ... 
- private 与 super
			public class Person { private String name; private int age; } public class Student extends Person { ... 
