Redis的“原子性自增”在订单编号策略中的简单应用

前言

通常情况下我们在系统中创建订单编号时,都会按照一定的规则去生成,因为订单编号是唯一的,不能重复的。

命名规则

例:业务编码+时间戳+流水号

方案

1、传统方案,比较主流的就是在数据库创建一个序列号表(sequence),然后在生成订单的时候,先使用一个含有事务的存储过程从sequence表获取当前订单号,然后在生成订单。但是这种方案过于复杂,在并发的情况下,事务会影响订单的生成速度。

2、Redis方案,首先Redis的原子性让我们可以不考虑并发的情况,利用原子性自增操作INCR时间计数器功能,再加上时间业务编码,时间戳此时就可生成一个流水号。

代码实现:

@Autowired
    private RedisTemplate redisTemplate;
/***
     * redis自增
     * @param key
     * @return
     */
    public Object getIncrValue(final String key){
        ValueOperations<String, String> valueOper = redisTemplate.opsForValue();
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        Object value = valueOper.increment(key,1);
        return value;
    }
/***
     * redis清空之后,保存从数据库中取出的流水号
     * @param key
     * @param value
     */
    public void setIncrValue(final String key,final String value){
        ValueOperations<String, String> valueOper = redisTemplate.opsForValue();
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        valueOper.set(key,value);
    }
import org.springframework.data.redis.core.RedisTemplate;

/***
     * 生成订单编号
     * @return
     */
    public String getOrderCode(long num) {
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;
        int day = c.get(Calendar.DAY_OF_MONTH);

        c.set(year, month - 1, day, 0, 0, 0);

        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //数字长度9位,长度不够数字前面补0
        String serialNum = String.format("%09d", num);
        return N+ year + month + day + serialNum;
    }

 附:redisZset的使用

   //zSet
    public void zSet(final String key,final Object value,Double score){
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();  
        zSetOperations.add(key, value, score);
    }
    
    //取出Zset
    public Set zRange(final String key){
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();  
        
        Set result = null;
        try {
            result = zSetOperations.range(key, 0, zSetOperations.size(key));
        } catch (Exception e) {
            result = null;
            e.printStackTrace();
        }
        return result;
    }
    
View Code
原文地址:https://www.cnblogs.com/4king/p/11814306.html