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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM