获取自增序号

  • springBoot使用redis获取自增序号
    • pom文件
    • 参考代码
      • 配置
      • 配置类代码
      • 使用代码
      • lua脚本
    • 测试代码
      • 配置
      • 配置类代码
      • 使用代码
      • lua脚本
      • lua脚本2
      • 输出
    • 另一种方式实现
      • 输出
  • end

springBoot使用redis获取自增序号

spring boot 集成 redis client

pom文件

    <parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.1.6.RELEASE</version><relativePath/></parent><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.1.6.RELEASE</spring-boot.version></properties><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId><version>${spring-boot.version}</version></dependency><dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>${lettuce.version}</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.5.0</version></dependency>

参考代码

配置

spring:redis:cluster:nodes: ip:portmax-redirects: 3
redis:timeout: 10000 #客户端超时时间单位是毫秒 默认是2000maxIdle: 300 #最大空闲数maxTotal: 1000 #控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性maxWaitMillis: 1000 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。minEvictableIdleTimeMillis: 300000 #连接的最小空闲时间 默认1800000毫秒(30分钟)numTestsPerEvictionRun: 1024 #每次释放连接的最大数目,默认3timeBetweenEvictionRunsMillis: 30000 #逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1testOnBorrow: true #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个testWhileIdle: true #在空闲时检查有效性, 默认false#password: 123456 #密码password: dataBase: 0

配置类代码

package cn.项目路径.config;import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.data.redis.config.ConfigureRedisAction;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;import java.time.Duration;
import java.util.HashSet;
import java.util.Set;/** redis 配置* @author tk* @date 2020/11/3 9:58*/
@Configuration
public class RedisConfig {@Value("${spring.redis.cluster.nodes}")private String clusterNodes;@Value("${spring.redis.cluster.max-redirects}")private Integer maxRedirects;@Value("${redis.password}")private String password;@Value("${redis.timeout}")private Integer timeout;@Value("${redis.maxIdle}")private Integer maxIdle;@Value("${redis.maxTotal}")private Integer maxTotal;@Value("${redis.maxWaitMillis}")private Integer maxWaitMillis;@Value("${redis.minEvictableIdleTimeMillis}")private Integer minEvictableIdleTimeMillis;@Value("${redis.numTestsPerEvictionRun}")private Integer numTestsPerEvictionRun;@Value("${redis.timeBetweenEvictionRunsMillis}")private Integer timeBetweenEvictionRunsMillis;@Value("${redis.testOnBorrow}")private boolean testOnBorrow;@Value("${redis.testWhileIdle}")private boolean testWhileIdle;@Value("${redis.dataBase}")private Integer dataBase;/** Redis集群的配置 */@Beanpublic RedisClusterConfiguration redisClusterConfiguration(){if(!clusterNodes.contains(",")) {return null;}RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();//Set<RedisNode> clusterNodesString[] serverArray = clusterNodes.split(",");Set<RedisNode> nodes = new HashSet<RedisNode>();for (String ipPort : serverArray) {String[] ipAndPort = ipPort.split(":");nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));}redisClusterConfiguration.setClusterNodes(nodes);redisClusterConfiguration.setMaxRedirects(maxRedirects);redisClusterConfiguration.setPassword(RedisPassword.of(password));return redisClusterConfiguration;}/** 集群redis 使用Lettuce集群模式 */@Beanpublic LettuceConnectionFactory lettuceConnectionFactory() {// 连接池配置GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();poolConfig.setMaxIdle(maxIdle);poolConfig.setMaxTotal(maxTotal);poolConfig.setMaxWaitMillis(maxWaitMillis);LettucePoolingClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(timeout)).shutdownTimeout(Duration.ofMillis(timeout)).poolConfig(poolConfig).build();LettuceConnectionFactory lettuceConnectionFactory = null;RedisClusterConfiguration redisClusterConfiguration = redisClusterConfiguration();/** 集群redis */if (redisClusterConfiguration != null) {lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);}else{/* 单机redis模式 */RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration(clusterNodes.split(":")[0],Integer.valueOf(clusterNodes.split(":")[1]));standaloneConfiguration.setPassword(password);lettuceConnectionFactory = new LettuceConnectionFactory(standaloneConfiguration, lettuceClientConfiguration);}lettuceConnectionFactory.setDatabase(dataBase);return lettuceConnectionFactory;}/** 实例化 RedisTemplate 对象 */@Beanpublic RedisTemplate<String, Object> redisTemplate() {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();initDomainRedisTemplate(redisTemplate);return redisTemplate;}/** 设置数据存入 redis 的序列化方式,并开启事务* 使用默认的序列化会导致key乱码 */private void initDomainRedisTemplate(RedisTemplate <String, Object> redisTemplate) {//如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!redisTemplate.setKeySerializer(new StringRedisSerializer());//这个地方有一个问题,这种序列化器会将value序列化成对象存储进redis中,如果//你想取出value,然后进行自增的话,这种序列化器是不可以的,因为对象不能自增;//需要改成StringRedisSerializer序列化器。redisTemplate.setValueSerializer(new StringRedisSerializer());redisTemplate.setEnableTransactionSupport(false);/** lettuce 集群模式 */redisTemplate.setConnectionFactory(lettuceConnectionFactory());redisTemplate.afterPropertiesSet();}@Beanpublic static ConfigureRedisAction configureRedisAction() {return ConfigureRedisAction.NO_OP;}@Beanpublic CookieSerializer httpSessionIdResolver(){DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();cookieSerializer.setUseHttpOnlyCookie(false);cookieSerializer.setSameSite(null);return cookieSerializer;}
}

使用代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;@Component
public class IDUtil {private final RedisTemplate<String, String> redisTemplate;@Autowiredpublic IDUtil(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}public String genNo(){DefaultRedisScript script = new DefaultRedisScript<>();script.setResultType(Long.class);script.setScriptSource(new ResourceScriptSource(new ClassPathResource("id.lua")));List<String> key = new ArrayList<>(1);key.add("genid");Object result = redisTemplate.execute(script, key, "1", "9999");return result.toString();}
}

lua脚本

local curr = redis.call('GET',KEYS[1]);
if( curr == false) thenredis.call('SET',KEYS[1],0)
elseif curr and tonumber(curr) >= tonumber(ARGV[2]) thenredis.call('SET',KEYS[1],0)return 0
elseredis.call('incrby',keys[1],ARGV[1])return curr + ARGV[1]
end

测试代码

配置

spring:redis:host: localhostport: 6379password: database: 0timeout: 10000mslettuce:pool:max-active: 50max-wait: -1max-idle: 8

配置类代码

package cn.**.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** RedisConfig 类说明:** @author z.y* @version v1.0* @date 2021/10/26*/
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// key 使用 字符串序列化template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new StringRedisSerializer());template.setEnableTransactionSupport(false);template.setHashKeySerializer(new StringRedisSerializer());valueSerializer(template);// 其余 属性 使用默认设置template.afterPropertiesSet();return template;}private void valueSerializer(RedisTemplate<String, Object> template){// 对象 使用 json 序列化Jackson2JsonRedisSerializer<?> jrs = new Jackson2JsonRedisSerializer<Object>(Object.class);ObjectMapper mapper = new ObjectMapper();mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jrs.setObjectMapper(mapper);template.setHashValueSerializer(jrs);}
}

使用代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;@Component
public class RedisCommon{private final RedisTemplate<String, Object> redisTemplate;private ValueOperations<String, Object> ops;private DefaultRedisScript<Long> script;@Autowiredpublic RedisCommon(RedisTemplate<String, Object> redisTemplate) {this.redisTemplate = redisTemplate;ops = redisTemplate.opsForValue();script = new DefaultRedisScript<>();script.setResultType(Long.class);script.setScriptSource(new ResourceScriptSource(new ClassPathResource("id.lua")));}/** 使用 redis 生成 序号* @param endKey 后缀key* @param max 序号最大值* @param expire 存活时长* @return 序号*/public Long genNo(String endKey,String max,String expire){List<String> key = new ArrayList<>(1);key.add("CN:ZY:GEN:"+endKey);return redisTemplate.execute(script, key, "1", max ,expire);}public Long genNo(String key){return genNo(key,"999999","86400");}
}

lua脚本

local curr = redis.call('GET',KEYS[1]);
if( curr == false) thenredis.call('SET',KEYS[1],0)if ( ARGV[3] ~= nil) thenredis.call('EXPIRE',KEYS[1],ARGV[3])endreturn 0
elseif curr and tonumber(curr) >= tonumber(ARGV[2]) thenredis.call('SET',KEYS[1],0)if ( ARGV[3] ~= nil) thenredis.call('EXPIRE',KEYS[1],ARGV[3])endreturn 0
elseredis.call('INCRBY',keys[1],ARGV[1])return curr + ARGV[1]
end

lua脚本2

local curr = redis.call('GET',KEYS[1]);
if( curr == false or (curr and tonumber(curr) >= tonumber(ARGV[2])) ) thenredis.call('SET',KEYS[1],0)if ( ARGV[3] ~= nil) thenredis.call('EXPIRE',KEYS[1],ARGV[3])endreturn 0
elsereturn redis.call('INCRBY',keys[1],ARGV[1])
end

输出

另一种方式实现

这种方式 不用写 lua脚本,更简洁
spring boot整合redisTemplate获取自增主键incr

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Component
public class RedisCommon{private final RedisTemplate<String, Object> redisTemplate;@Autowiredpublic RedisCommon(RedisTemplate<String, Object> redisTemplate) {this.redisTemplate = redisTemplate;}public Long genNo2(String endKey, long liveTime){RedisAtomicLong ral = new RedisAtomicLong("CN:ZY:GEN:"+endKey, redisTemplate.getConnectionFactory());long l = ral.getAndIncrement();if ( ral.longValue() <= 1 && liveTime > 0) {ral.expire(liveTime, TimeUnit.SECONDS);}return l;}
}

输出

0
1
2

end

springBoot使用redis获取自增序号相关推荐

  1. SpringBoot整合redisTemplate获取自增主键

    SpringBoot整合redisTemplate获取自增主键 在Spring Boot应用程序中,我们可以使用Redis作为缓存或数据存储.当我们使用Redis存储数据时,我们可能需要使用自增主键. ...

  2. springboot对于redis的增删改查

    springboot对于redis的增删改查 1.下载redis,安装之后,打开redis服务器.不过有绿色版的,直接打开redis服务器可执行文件,启动redis服务器. 2.在pom.xml配置文 ...

  3. 获取数据表里的下一个自增序号

    查询table 下一个将要生成的id值 SELECT IDENT_CURRENT('table') + IDENT_INCR('table'); 查询table当前最大的id值,自增序号 SELECT ...

  4. 在线博客系统——文章详情(redis incr自增实现增加阅读数和评论数)

    目录 文章详情 接口说明 编码实现 Controller控制层 Service业务逻辑层 前端测试 redis incr自增实现浏览量 Redis配置类 Redis工具类 Dao持久层准备 Mappe ...

  5. springboot 集成 redis 工具类

    添加依赖 <!-- SpringBoot Boot Redis --><dependency><groupId>org.springframework.boot&l ...

  6. Redis学习(含 Springboot 整合 Redis)

    Redis NoSQL (not only sql) 在现代的计算系统上每天网络上都会产生庞大的数据量. 这些数据有很大一部分是由关系数据库管理系统(RDBMS)来处理. 1970年 E.F.Codd ...

  7. javamailsender注入失败_关于SpringBoot使用Redis空指针的问题(不能成功注入的问题)...

    自己的一个小项目使用redis在一个类里可以注入成功,而在另一个类以却不能注入成功 不多bb直接上代码 package com.common.utils; import org.springframe ...

  8. springboot整合redis、mybatis、@EnableScheduling定时任务,实现日访问量与日活量的统计与记录

    目录 一.实现目标 二.windows版本redis下载与安装 三.springboot集成redis 四.springboot集成mybatis 集成通用mapper 五.实现日访问量 @Enabl ...

  9. springboot+shiro+redis+jwt实现多端登录:PC端和移动端同时在线(不同终端可同时在线)

    前言 之前写了篇 springboot+shiro+redis多端登录:单点登录+移动端和PC端同时在线 的文章,但是token用的不是 jwt 而是 sessionID,虽然已经实现了区分pc端和移 ...

最新文章

  1. java 连接 oracle 10_java 怎么把原本连接32位oracle10g换到连接64位oracle10g
  2. 【winform程序】自定义webrowser控件调用IE的版本
  3. Check failed: registry.count(type) == 1 (0 vs. 1) Unknown layer type: Python
  4. sql 分类汇总 列_分类汇总哪家强?R、Python、SAS、SQL?
  5. git linux 登陆_Git安装及基础命令
  6. mysql5.7免安版配置_mysql5.7免安装版配置
  7. 解码(六):sws_scale像素格式转换代码演示
  8. UIView Methods
  9. 多时隙编码aloha(MuSCA)与编码时隙aloha(CSA)协议分析
  10. 3-5-多数组k大值
  11. 百度文库文档 下载券文档 代下载 原格式不变
  12. 阿里美女面试官问我:Flink资源管理有了解吗
  13. 条件概率公式图解推导
  14. linear-gradient实现Ps标尺
  15. EXPLAIN 使用
  16. Mysql数据库的分离和附加
  17. 低频数字相位测量仪的介绍
  18. 给飞机叶片穿戴上3D打印传感器
  19. android沉浸式+虚拟按键+Fragment+CoordinatorLayout(2)
  20. CDH 安装,CDH中安装Nifi

热门文章

  1. 检查 GPU 渲染速度和过度绘制
  2. word 删除带分节符的空白页
  3. ssm保险办理系统毕业设计源码012232
  4. 用一个sql查询将url匹配的排在最前,title匹配的其次,body匹配最后
  5. HTML中插入自动播放的背景音乐-亲测有效
  6. AutoCAD Civil 3D-超高及数据编辑输入
  7. vue集成capacitor
  8. .net System.Web.Mail发送邮件 (已过时)
  9. 【竞赛复盘】2022雪浪算力开发者大赛——阀体异常检测
  10. 跨境电商业务拓展专用服务器,腾讯云海外轻量应用服务器