最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

大白話講解調用Redis的increment失敗原因及推薦使用詳解

 更新時間:2021年11月11日 08:55:59   作者:哎喔別走  
本文主要介紹了調用Redis的increment失敗原因及推薦使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

大家在項目中基本都會接觸到redis,在spring-data-redis-2.*.*.RELEASE.jar中提供了兩個Helper class,可以讓我們更方便的操作redis中存儲的數(shù)據(jù)。這兩個Helper class分別是RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是RedisTemplate在存儲String類型的時候的一個擴展子類。所以大家在使用redis的時候:

1、如果操作的是String類型,優(yōu)先考慮用StringRedisTemplate;

2、如果是復雜對象類型,則有限考慮RedisTemplate。

       如果大家在使用redis來進行計數(shù)場景,比如記錄調用次數(shù)、記錄接口的調用閾值等,用RedisTemplate出現(xiàn)了以下錯誤ERR value is not an integer or out of range,那么先說下解決方案,如下:

//類中直接注入StringRedisTemplate 
@Autowired
private StringRedisTemplate stringRedisTemplate;

//方法體中用以下方式進行計數(shù)
stringRedisTemplate.opsForValue().increment("check:incr:str");

即用StringRedisTemplate代替RedisTemplate。

        出現(xiàn)上面的原因,就是因為序列化導致的。我們知道數(shù)據(jù)是以二進制形式存儲在redis的,那么就必然涉及到序列化和反向序列化,上面提到的這兩個Helper class就可以自動的幫我們實現(xiàn)序列化和反向序列,其中二者的主要區(qū)別就是序列化機制,

1、StringRedisTemplate的序列化機制是通過StringRedisSerializer來實現(xiàn)的;

2、RedisTemplate的序列化機制是通過JdkSerializationRedisSerializer來實現(xiàn)的。

        increment操作底層就是讀取數(shù)據(jù),然后+1,然后set,只不過這三個步驟被redis加了原子操作保證,所以我們從StringRedisTemplate和RedisTemplate的set方法來分析。先看StringRedisTemplate的源碼如下:

1、stringRedisTemplate.opsForValue().set("check:incr:str", "1");

2、查看第一步的set方法,進入DefaultValueOperations類的set方法

@Override
public void set(K key, V value) {
  byte[] rawValue = rawValue(value);
  execute(new ValueDeserializingRedisCallback(key) {
    @Override
    protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
      connection.set(rawKey, rawValue);
      return null;
    }
  }, true);
}

3、查看第二步的處理value的rawValue方法,進入AbstractOperations.rawValue方法

@SuppressWarnings("unchecked")
byte[] rawValue(Object value) {
    if (valueSerializer() == null && value instanceof byte[]) {
        return (byte[]) value;
    }
    return valueSerializer().serialize(value);
}

4、看到第三步最終調用了序列化類對value做了序列化處理,我們知道StringRedisTemplate的序列化類StringRedisSerializer,
可知第三步的最后一行serialize最后調用了如下方法

@Override
public byte[] serialize(@Nullable String string) {
    return (string == null ? null : string.getBytes(charset));
}

5、到此我們知道了,value最后存在redis的最底層原理就是第四步的return返回的byte[]。那么就可以這樣認為,如果調用了
stringRedisTemplate.opsForValue().set("check:incr:str", "1");就好比是在redis存儲了"1".getBytes("UTF-8")

public static void main(String[] args) throws UnsupportedEncodingException {
  byte[] str = "1".getBytes("UTF-8");
  for(int i = 0 ; i< str.length; i++) {
    System.out.println(str[i]);
  }
}

結論:

上面main方法打印出來了49,了解了set方法后,可以猜測調用increment時相當于對49直接加1,變成50,get數(shù)據(jù)時再反向序列化可知對應是數(shù)字2

(注意標綠的是我的猜測,可以比較容易理解為什么可以直接increment,事實是否這樣需要看redis源碼,若有同學確認了,可以回復下我),

所以可以理解為什么StringRedisTemplate支持increment。

(注意這里并不是說RedisTemplate不支持,而是說RedisTemplate的默認配置的序列化實現(xiàn)機制,會導致RedisTemplate不支持increment)

接下來以同樣的方式,看RedisTemplate的源碼,如下: 

1、根據(jù)redisTemplate.opsForValue().set("check:incr:obj", 1);查看set方法
2、查看第一步的set方法,進入DefaultValueOperations類的set方法

@Override
public void set(K key, V value) {
  byte[] rawValue = rawValue(value);
  execute(new ValueDeserializingRedisCallback(key) {
    @Override
    protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
      connection.set(rawKey, rawValue);
      return null;
    }
  }, true);
}

3、查看第二步的處理value的rawValue方法,進入AbstractOperations.rawValue方法

@SuppressWarnings("unchecked")
byte[] rawValue(Object value) {
    if (valueSerializer() == null && value instanceof byte[]) {
        return (byte[]) value;
    }
    return valueSerializer().serialize(value);
}

4、看到第三步最終調用了序列化類對value做了序列化處理,我們知道RedisTemplate的序列化類是JdkSerializationRedisSerializer,可知第三步的最后一行serialize最后調用了JdkSerializationRedisSerializer的如下方法

@Override
public byte[] serialize(@Nullable Object object) {
    if (object == null) {
        return SerializationUtils.EMPTY_ARRAY;
    }
    try {
        return serializer.convert(object);
    } catch (Exception ex) {
        throw new SerializationException("Cannot serialize", ex);
    }
}

這里的serializer對象是SerializingConverter,可以知道實際調用的是SerializingConverter.convert(new Integer(1))

5、到此我們知道了,value最后存在redis的最底層原理就是第四步的return返回的byte[]。那么就可以這樣認為,如果調用了
RedisTemplate.opsForValue().set("check:incr:obj", 1);就好比是在redis存儲了下面方法的返回

public static void main(String[] args) throws UnsupportedEncodingException {
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
    try  {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream);
        objectOutputStream.writeObject(1);
        objectOutputStream.flush();
        byte[] obj = byteStream.toByteArray();
        for(int i=0; i<obj.length; i++) {
            System.out.println(obj[i]);
        }
    }catch (Throwable ex) {
        ex.printStackTrace();
    }
}

結論:
打印出來好多數(shù)據(jù),但是我們存儲的只是一個整數(shù)1而已,并且根據(jù)序列化過程中的類ObjectOutputStream
的描述(見下)可知序列化后會包含N多信息

/**
     * Write the specified object to the ObjectOutputStream.  The class of the
     * object, the signature of the class, and the values of the non-transient
     * and non-static fields of the class and all of its supertypes are
     * written.******
*/

到此這篇關于大白話講解調用Redis的increment失敗原因及推薦使用的文章就介紹到這了,更多相關Redis increment失敗原因內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Redis批量刪除指定前綴的Key兩種方法

    Redis批量刪除指定前綴的Key兩種方法

    redis作為緩存服務器在項目中經(jīng)常使用,使用redis存儲數(shù)據(jù)時,我們經(jīng)常會將key分組,這篇文章主要給大家介紹了關于Redis批量刪除指定前綴的Key兩種方法,需要的朋友可以參考下
    2024-01-01
  • redis中zSet實現(xiàn)排行榜的使用示例

    redis中zSet實現(xiàn)排行榜的使用示例

    在工作中,有時候需要實現(xiàn)排行榜功能,本文主要介紹了redis中zSet實現(xiàn)排行榜的使用示例,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • Redis中鍵的過期刪除策略深入講解

    Redis中鍵的過期刪除策略深入講解

    這篇文章主要給大家介紹了關于Redis中鍵的過期刪除策略的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-09-09
  • redis批量刪除key的步驟

    redis批量刪除key的步驟

    本文分享最新版Redis批量刪除key的方法,希望能幫到遇到同樣問題的網(wǎng)友。
    2020-09-09
  • 在redisCluster中模糊獲取key方式

    在redisCluster中模糊獲取key方式

    這篇文章主要介紹了在redisCluster中模糊獲取key方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 詳解Redis單線程架構的優(yōu)勢與不足

    詳解Redis單線程架構的優(yōu)勢與不足

    很多人都遇到過這么一道面試題:Redis是單線程還是多線程?這個問題既簡單又復雜,說他簡單是因為大多數(shù)人都知道Redis是單線程,說復雜是因為這個答案其實并不準確,本文就給大家講講Redis單線程架構的優(yōu)勢與不足,需要的朋友可以參考下
    2024-02-02
  • Redis數(shù)據(jù)結構之鏈表與字典的使用

    Redis數(shù)據(jù)結構之鏈表與字典的使用

    這篇文章主要介紹了Redis數(shù)據(jù)結構之鏈表與字典的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • redis.conf中使用requirepass不生效的原因及解決方法

    redis.conf中使用requirepass不生效的原因及解決方法

    本文主要介紹了如何啟用requirepass,以及啟用requirepass為什么不會生效,從代碼層面分析了不生效的原因,以及解決方法,需要的朋友可以參考下
    2023-07-07
  • 深入理解redis_memcached失效原理(小結)

    深入理解redis_memcached失效原理(小結)

    這篇文章主要介紹了深入理解redis_memcached失效原理(小結),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • Redis中有序集合的內部實現(xiàn)方式的詳細介紹

    Redis中有序集合的內部實現(xiàn)方式的詳細介紹

    本文主要介紹了Redis中有序集合的內部實現(xiàn)方式的詳細介紹,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論

光泽县| 化州市| 临泉县| 特克斯县| 南华县| 当雄县| 靖安县| 云阳县| 阳高县| 桃江县| 镇沅| 宁强县| 宝丰县| 桂阳县| 英吉沙县| 宣武区| 临澧县| 泸州市| 碌曲县| 阿拉善左旗| 武汉市| 丹东市| 手机| 樟树市| 察哈| 绥德县| 武冈市| 武定县| 临颍县| 焉耆| 犍为县| 桓台县| 普安县| 九龙县| 长沙市| 东辽县| 梓潼县| 大田县| 潞西市| 基隆市| 华阴市|