首页 > 数据库 >java 使用Redis的INCR命令或Lua脚本来实现分布式应用生成唯一性ID

java 使用Redis的INCR命令或Lua脚本来实现分布式应用生成唯一性ID

时间:2024-04-11 11:25:00浏览次数:25  
标签:INCR java Lua 递增 Redis 分布式应用 命令 jedis

在Java中使用Redis的INCR命令或Lua脚本来生成分布式应用中的唯一性ID是一个常见的做法。以下是如何实现这两种方法的简要说明。

1、使用Redis的INCR命令

Redis的INCR命令是一个用于递增存储在键中的整数值的原子操作。如果键不存在,那么它将被初始化为0再进行递增操作。

命令格式

INCR key

工作原理

    1. 查找键:Redis首先查找指定的键(key)。
    1. 检查键的类型:如果键存在,Redis会检查其类型。只有存储整数值的键才能使用INCR命令。如果键不是整数,Redis会返回一个错误。
    1. 递增操作:如果键存在且是整数类型,Redis会将该整数值加1。
    1. 初始化新键:如果键不存在,Redis会创建一个新的键,并将其初始化为0,然后再进行递增操作。
    1. 返回结果:最后,INCR命令会返回递增后的整数值。

使用示例

假设你有一个名为pageviews:homepage的键,用于跟踪主页的访问次数。你可以使用INCR命令来递增这个值:

SET pageviews:homepage 0
OK
INCR pageviews:homepage
(integer) 1
INCR pageviews:homepage
(integer) 2
INCR pageviews:homepage
(integer) 3

注意事项

  • INCR命令是原子性的,这意味着在递增操作完成之前,不会有其他命令能够修改该键的值。这保证了在多客户端并发访问的情况下,计数器的准确性。
  • INCR命令只能用于整数类型的键。如果尝试对非整数类型的键使用INCR命令,Redis会返回一个错误。
  • 由于INCR命令会修改键的值,因此它也会影响与该键相关的持久化策略和内存使用情况。

替代命令

除了INCR命令外,Redis还提供了DECR(递减)、INCRBY(按指定值递增)和DECRBY(按指定值递减)等命令,用于更灵活地处理整数值的增减操作。
public class RedisIdGenerator {
private Jedis jedis;
private String idKey = "unique-id";
private long initialValue = 0L;

public RedisIdGenerator(Jedis jedis) {  
    this.jedis = jedis;  
    // 确保初始值存在,如果不存在则设置为initialValue  
    if (!jedis.exists(idKey)) {  
        jedis.set(idKey, String.valueOf(initialValue));  
    }  
}  

public synchronized long generateId() {  
    // 使用INCR命令递增ID,并返回新值  
    return jedis.incr(idKey);  
}  

}

2、使用Lua脚本

Lua脚本可以在Redis服务器端执行一系列命令,并且这些命令是原子性的,即它们要么全部成功执行,要么全部不执行。这对于生成唯一ID特别有用,因为它可以确保在生成ID的过程中不会出现竞态条件。
public class RedisIdGeneratorWithLua {
private Jedis jedis;
private String luaScript;
private String idKey = "unique-id";

public RedisIdGeneratorWithLua(Jedis jedis) {  
    this.jedis = jedis;  
    this.luaScript =   
        "local key = KEYS[1]\n" +  
        "local currentValue = redis.call('get', key)\n" +  
        "if currentValue then\n" +  
        "    currentValue = tonumber(currentValue) + 1\n" +  
        "    redis.call('set', key, currentValue)\n" +  
        "    return currentValue\n" +  
        "else\n" +  
        "    redis.call('set', key, 1)\n" +  
        "    return 1\n" +  
        "end";  
}  

public long generateId() {  
    // 执行Lua脚本并返回结果  
    return (long) jedis.eval(luaScript, 1, idKey);  
}  

}
在这个示例中,eval方法的第一个参数是Lua脚本,第二个参数是键的数量(在这里是1),后面跟着的是键的实际值。这个Lua脚本会原子地检查键是否存在,如果存在则递增其值,否则初始化键并返回1。由于Lua脚本的执行是原子的,所以即使在高并发的情况下,生成的ID也是唯一的。

标签:INCR,java,Lua,递增,Redis,分布式应用,命令,jedis
From: https://www.cnblogs.com/wjf-learning/p/18128473

相关文章

  • Java中将字符串转换成数字的方法
    转换为整数(int)你可以使用Integer.parseInt()方法或Integer.valueOf()方法将字符串转换为int类型。javaStringstr="123";intnumber=Integer.parseInt(str);//使用parseInt//或者intnumberValue=Integer.valueOf(str);//使用valueOfSystem.out.println(number);//......
  • java UTC时间格式化
    importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Date;importjava.util.TimeZone;/***@author王睿*@date2019-01-2414:32*/publicclassTimeFormat{publicstaticvoidmain(String[]args)throwsParseExcept......
  • JAVA System.getProperty() 与 System.getenv() 差异及示例
    System.getenv() 方法是获取指定的环境变量的值。System.getenv() 接收参数为任意字符串,当存在指定环境变量时即返回环境变量的值,否则返回null。System.getProperty() 是获取系统的相关属性,包括文件编码、操作系统名称、区域、用户名等,此属性一般由jvm自动获取,不能设置。Sys......
  • java计算机毕业设计基于微信小程序的书籍销售系统【附源码+远程部署+程序+mysql】
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着移动互联网技术的飞速发展,智能手机用户数量急剧增加,人们获取信息和进行日常交易的方式正逐步向移动端转移。微信作为中国最流行的社交通讯软件,其推出......
  • Java商城免费搭建 VR全景商城 saas商城 b2b2c商城 o2o商城 积分商城 秒杀商城 拼团商
    1.涉及平台平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2.核心架构SpringCloud、SpringBoot、Mybatis、Redis3.前端框架VUE、Uniapp、Bootstrap/H5/CSS3、IOS、Android、小程序4.核心思想分布式、微服务、......
  • java分布式应用生成唯一性ID的方案
    在Java分布式应用中生成唯一性ID是一个常见的需求。以下是一些常用的方案:1.UUID(UniversallyUniqueIdentifier):UUID是一个128位的字符串,通常按照8-4-4-4-12的格式呈现,例如:550e8400-e29b-41d4-a716-446655440000。Java中的java.util.UUID类提供了生成UUID的方法。优点:无需查......
  • JAVA学习-深入研究容器.选择接口的不同实现
        Java集合框架提供了多个接口,每个接口都有不同的实现类,以满足不同的需求。以下是几个常用接口及其不同的实现类的概述:1.List接口:  -特点:有序集合,允许重复元素。  -实现类:ArrayList、LinkedList、Vector。  -使用方法:使用add()方法添加元素,使用g......
  • java 内部类
    在Java中,可以将一个类定义在另一个类里面或者一个方法里边,这样的类称为内部类,广泛意义上的内部类一般包括四种:成员内部类,局部内部类,匿名内部类,静态内部类。1.成员内部类(1)该类像是外部类的一个成员,可以无条件的访问外部类的所有成员属性和成员方法(包括private成员和静态成员);(2)成......
  • Java List集合去重、过滤、分组、获取数据、求最值、合并、排序、跳数据和遍历
    前言请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i、准备工作:现有一个User类、Student类和Ticket类,加入相关依赖@DatapublicclassUser{/***id*/privateIntegerid;/***姓名*/privateStringname;/**......
  • JavaScript处理异步循环的技术详解
    文章的更新路线:JavaScript基础知识-Vue2基础知识-Vue3基础知识-TypeScript基础知识-网络基础知识-浏览器基础知识-项目优化知识-项目实战经验-前端温习题(HTML基础知识和CSS基础知识已经更新完毕)正文使用async/await和Promise:优势:代码简洁,易读,适用于处理依赖关系较强......