redis 某键值自增 redis自增序列方案_序列号


前言

Redis作为时下热门的缓存数据库,由于单线程、直接存取与内存中,所以速度很快很高效。redis的使用场景也非常多样化,常见的是作为优秀的缓存中间件,减轻数据库压力。下面就以springBoot和SpringMvc为例子来介绍一下使用Redis获取自增序列号。


项目实例

SpringBoot

1.pom文件引入
springBoot有对redis的封装插件,直接按以下引入即可:


<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>


2.yml或者properties配置redis连接的相关信息


#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.timeout=3000
spring.redis.password=shit


3.添加redis配置类,可以实例化redisTemplate,设置缓存失效时间等,以及redis连接池等,这里从简了


@Configuration
public class RedisConfig {

     @Bean
     public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
          StringRedisTemplate template = new StringRedisTemplate(factory);
          //序列化方式 
          Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
          ObjectMapper objectMapper = new ObjectMapper();
          objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
          objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
          jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
          template.setValueSerializer(jackson2JsonRedisSerializer);
          template.afterPropertiesSet();
          return template;
     }

}


4.按照key获取递增的序列号


/**
      * 获取递增的序列号
      *
      * @param prefix 生成序列号的前缀
      * @return
      */
     public String getIncre(String prefix) {
          //序列号前缀加特定标识,如系统模块名之类的 防止重复
          String key = "SCM_DAMLL" + prefix;
          String increResult = null;
          try {
               //如果该key不存在 会自动创建,值为第二个参数delta
               //最终调用的还是jedis的incrBy(byte[] key, long value)方法
               Long increNum = redisTemplate.opsForValue().increment(key, 1);
               //不足补位
               increResult = prefix + String.format("%1$06d", increNum);
          } catch (Exception e) {
               logger.infor("获取序列号失败");
               /*这里可以根据需求手动生成一个不重复的单号,
               * */
          }
          return increResult;
     }


springMVC

springMVC通常引入jedis包来进行redis相关的操作,和上诉spring-boot-starter-data-redis相比,jedis封装度更低,更加原生态,操作方式和一些方法更接近于redis命令操作。1.pom文件引入


<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.2.1</version>
        </dependency>


2.redis连接配置


redis.host=127.0.0.1
redis.port=6379
redis.maxWait=1000000
redis.password=shit
redis.maxIdle=300
redis.maxTotal=60000


3.在spring配置文件中实例化对象


<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}"/> 
        <property name="maxActive" value="${redis.maxTotal}"/> 
        <property name="testOnBorrow" value="true"/> 
    </bean>

    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
        <constructor-arg name="host" value="${redis.host}"/>
        <constructor-arg name="port" value="${redis.port}" type="int"/>
        <constructor-arg name="timeout" value="${redis.maxWait}"/>
        <constructor-arg name="password" value="${redis.password}"/>
    </bean>


4.编写一个redis操作的工具类


@Component
public class JedisUtil {
     protected final static Logger logger = Logger.getLogger(JedisUtil.class);

     private static JedisPool jedisPool;

     @Autowired(required = true)
     public void setJedisPool(JedisPool jedisPool) {
          JedisUtil.jedisPool = jedisPool;
     }

     /**
      * 获取自增的序列号
      *
      * @param key redis主键
      * @return
      */
     public static String getIncreNum(String key) {

          String value = null;
          Jedis jedis = null;
          try {
               jedis = jedisPool.getResource();
               value = jedis.incrBy(key, 1).toString();
          } catch (Exception e) {
               logger.warn("getList " + key + " = " + value);
          } finally {
               jedisPool.returnResource(jedis);
          }
          return value;
     }
}


以上未考虑到redis集群的情况,常规生成序列号是够用了,每次获取序列号的时间也在1毫秒左右,非常高效,同时列出其他生成连续号段的方法。

  1. 取mysql自增主键id,每次插入前查询当前库max(id) ,优点:简单,缺点:增加数据库查询次数,高并发考虑maxid与实际值不一致情况
  2. 创建序列号的表,存储序列值,通过添加版本号字段或加锁控制写入 优点:准确 缺点:效率低

结尾

谢谢大家看到最后,既然都看最后了点个赞再走吧,汽水在这里谢谢大家了,如有不对之处还请多多指正。