栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springBoot使用redis获取自增序号

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springBoot使用redis获取自增序号

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

springBoot使用redis获取自增序号

spring boot 集成 redis client

pom文件
    
        spring-boot-starter-parent
        org.springframework.boot
        2.1.6.RELEASE
        
    
    
        1.8
        UTF-8
        UTF-8
        2.1.6.RELEASE
    
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.springframework.session
        spring-session-data-redis
        ${spring-boot.version}
    
    
        io.lettuce
        lettuce-core
        ${lettuce.version}
    
    
        org.apache.commons
        commons-pool2
        2.5.0
    
参考代码 配置
spring:
  redis:
    cluster:
      nodes: ip:port
      max-redirects: 3
redis:
  timeout: 10000 #客户端超时时间单位是毫秒 默认是2000
  maxIdle: 300 #最大空闲数
  maxTotal: 1000 #控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
  maxWaitMillis: 1000 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
  minEvictableIdleTimeMillis: 300000 #连接的最小空闲时间 默认1800000毫秒(30分钟)
  numTestsPerEvictionRun: 1024 #每次释放连接的最大数目,默认3
  timeBetweenEvictionRunsMillis: 30000 #逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
  testOnBorrow: 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;


@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;

    
    @Bean
    public RedisClusterConfiguration redisClusterConfiguration(){
        if(!clusterNodes.contains(",")) {
            return null;
        }
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
        //Set clusterNodes
        String[] serverArray = clusterNodes.split(",");
        Set nodes = new HashSet();
        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;
    }
    
    @Bean
    public 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();
        
        if (redisClusterConfiguration != null) {
            lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
        }else{
            
            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;
    }
    
    @Bean
    public RedisTemplate redisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate);
        return redisTemplate;
    }
    
    private void initDomainRedisTemplate(RedisTemplate  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);
        
        redisTemplate.setConnectionFactory(lettuceConnectionFactory());
        redisTemplate.afterPropertiesSet();
    }

    @Bean
    public static ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }

    @Bean
    public 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 redisTemplate;
    @Autowired
    public IDUtil(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    public String genNo(){
		DefaultRedisscript script = new DefaultRedisscript<>();
		script.setResultType(Long.class);
		script.setscriptSource(new ResourcescriptSource(new ClassPathResource("id.lua")));
		List 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) then
	redis.call('SET',KEYS[1],0)
elseif curr and tonumber(curr) >= tonumber(ARGV[2]) then
	redis.call('SET',KEYS[1],0)
	return 0
else
	redis.call('incrby',keys[1],ARGV[1])
	return curr + ARGV[1]
end
测试代码 配置
spring:
  redis:
    host: localhost
    port: 6379
    password: 
    database: 0
    timeout: 10000ms
    lettuce:
      pool:
        max-active: 50
        max-wait: -1
        max-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;


@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        RedisTemplate 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 template){
        // 对象 使用 json 序列化
        Jackson2JsonRedisSerializer jrs = new Jackson2JsonRedisSerializer(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 redisTemplate;
    private ValueOperations ops;
    private DefaultRedisscript script;
    @Autowired
    public RedisCommon(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
        ops = redisTemplate.opsForValue();
        script = new DefaultRedisscript<>();
		script.setResultType(Long.class);
		script.setscriptSource(new ResourcescriptSource(new ClassPathResource("id.lua")));
    }
    
    public Long genNo(String endKey,String max,String expire){
		List 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) then
	redis.call('SET',KEYS[1],0)
	if ( ARGV[3] ~= nil) then
		redis.call('EXPIRE',KEYS[1],ARGV[3])
	end
	return 0
elseif curr and tonumber(curr) >= tonumber(ARGV[2]) then
	redis.call('SET',KEYS[1],0)
	if ( ARGV[3] ~= nil) then
		redis.call('EXPIRE',KEYS[1],ARGV[3])
	end
	return 0
else
	redis.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])) ) then
	redis.call('SET',KEYS[1],0)
	if ( ARGV[3] ~= nil) then
		redis.call('EXPIRE',KEYS[1],ARGV[3])
	end
	return 0
else
	return redis.call('INCRBY',keys[1],ARGV[1])
end
输出

end
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号