zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    记录一个Heisenbug!
    MATLAB(一):矩阵基本操作
    MATLAB基础(三):MATLAB基本运算与字符串处理
    MATLAB基础(二):变量与矩阵
    MATLAB基础(一):简介及数值数据特点与常用数学函数
    用位运算实现四则运算
    指针:C语言二级指针与二维数组
    单片机基础(八):单片机串行口结构与工作方式及应用
    单片机基础(七):串行通信概念及其工作原理
    单片机基础(六):单片机定时/控制器的控制接口
  • 原文地址:https://www.cnblogs.com/4king/p/11814306.html
Copyright © 2011-2022 走看看