欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

大白話講解調(diào)用Redis的increment失敗原因及推薦使用詳解

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

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

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

2、如果是復(fù)雜對(duì)象類型,則有限考慮RedisTemplate。

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

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

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

即用StringRedisTemplate代替RedisTemplate。

        出現(xiàn)上面的原因,就是因?yàn)樾蛄谢瘜?dǎo)致的。我們知道數(shù)據(jù)是以二進(jìn)制形式存儲(chǔ)在redis的,那么就必然涉及到序列化和反向序列化,上面提到的這兩個(gè)Helper class就可以自動(dòng)的幫我們實(shí)現(xiàn)序列化和反向序列,其中二者的主要區(qū)別就是序列化機(jī)制,

1、StringRedisTemplate的序列化機(jī)制是通過(guò)StringRedisSerializer來(lái)實(shí)現(xiàn)的;

2、RedisTemplate的序列化機(jī)制是通過(guò)JdkSerializationRedisSerializer來(lái)實(shí)現(xiàn)的。

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

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

2、查看第一步的set方法,進(jìn)入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方法,進(jìn)入AbstractOperations.rawValue方法

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

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

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

5、到此我們知道了,value最后存在redis的最底層原理就是第四步的return返回的byte[]。那么就可以這樣認(rèn)為,如果調(diào)用了
stringRedisTemplate.opsForValue().set("check:incr:str", "1");就好比是在redis存儲(chǔ)了"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]);
  }
}

結(jié)論:

上面main方法打印出來(lái)了49,了解了set方法后,可以猜測(cè)調(diào)用increment時(shí)相當(dāng)于對(duì)49直接加1,變成50,get數(shù)據(jù)時(shí)再反向序列化可知對(duì)應(yīng)是數(shù)字2

(注意標(biāo)綠的是我的猜測(cè),可以比較容易理解為什么可以直接increment,事實(shí)是否這樣需要看redis源碼,若有同學(xué)確認(rèn)了,可以回復(fù)下我),

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

(注意這里并不是說(shuō)RedisTemplate不支持,而是說(shuō)RedisTemplate的默認(rèn)配置的序列化實(shí)現(xiàn)機(jī)制,會(huì)導(dǎo)致RedisTemplate不支持increment)

接下來(lái)以同樣的方式,看RedisTemplate的源碼,如下: 

1、根據(jù)redisTemplate.opsForValue().set("check:incr:obj", 1);查看set方法
2、查看第一步的set方法,進(jìn)入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方法,進(jìn)入AbstractOperations.rawValue方法

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

4、看到第三步最終調(diào)用了序列化類對(duì)value做了序列化處理,我們知道RedisTemplate的序列化類是JdkSerializationRedisSerializer,可知第三步的最后一行serialize最后調(diào)用了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對(duì)象是SerializingConverter,可以知道實(shí)際調(diào)用的是SerializingConverter.convert(new Integer(1))

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

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();
    }
}

結(jié)論:
打印出來(lái)好多數(shù)據(jù),但是我們存儲(chǔ)的只是一個(gè)整數(shù)1而已,并且根據(jù)序列化過(guò)程中的類ObjectOutputStream
的描述(見下)可知序列化后會(huì)包含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.******
*/

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

相關(guān)文章

  • spring?boot整合redis中間件與熱部署實(shí)現(xiàn)代碼

    spring?boot整合redis中間件與熱部署實(shí)現(xiàn)代碼

    spring?boot整合redis最常用的有三個(gè)工具庫(kù)Jedis,Redisson,Lettuce,本文重點(diǎn)介紹spring?boot整合redis中間件與熱部署實(shí)現(xiàn),需要的朋友可以參考下
    2023-01-01
  • Redis實(shí)現(xiàn)訂單自動(dòng)過(guò)期功能的示例代碼

    Redis實(shí)現(xiàn)訂單自動(dòng)過(guò)期功能的示例代碼

    這篇文章主要介紹了Redis實(shí)現(xiàn)訂單自動(dòng)過(guò)期功能的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Spring boot+redis實(shí)現(xiàn)消息發(fā)布與訂閱的代碼

    Spring boot+redis實(shí)現(xiàn)消息發(fā)布與訂閱的代碼

    這篇文章主要介紹了Spring boot+redis實(shí)現(xiàn)消息發(fā)布與訂閱,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值需要的朋友可以參考下
    2020-04-04
  • Windows下搭建Redis哨兵集群模式的方法步驟

    Windows下搭建Redis哨兵集群模式的方法步驟

    哨兵模式,是基于主從復(fù)制模式,主從復(fù)制的優(yōu)點(diǎn)全都擁有,并且主從可以實(shí)現(xiàn)自動(dòng)切換,故障轉(zhuǎn)移等功能,本文主要介紹了Windows下搭建Redis哨兵集群模式的方法步驟,文中通過(guò)圖文介紹的非常詳細(xì),感興趣的小伙伴們可以參考一下,需要的朋友可以參考下
    2023-09-09
  • Redis Set 集合的實(shí)例詳解

    Redis Set 集合的實(shí)例詳解

    這篇文章主要介紹了 Redis Set 集合的實(shí)例詳解的相關(guān)資料,Redis的Set是string類型的無(wú)序集合。集合成員是唯一的,并且不重復(fù),需要的朋友可以參考下
    2017-08-08
  • Redis序列化反序列化不一致導(dǎo)致String類型值多了雙引號(hào)問(wèn)題

    Redis序列化反序列化不一致導(dǎo)致String類型值多了雙引號(hào)問(wèn)題

    這篇文章主要介紹了Redis序列化反序列化不一致導(dǎo)致String類型值多了雙引號(hào)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • redis cluster支持pipeline的實(shí)現(xiàn)思路

    redis cluster支持pipeline的實(shí)現(xiàn)思路

    本文給大家介紹redis cluster支持pipeline的實(shí)現(xiàn)思路,在 cluster 上執(zhí)行 pipeline 可能會(huì)由于 redis 節(jié)點(diǎn)擴(kuò)縮容 中途 redirection 切換連接導(dǎo)致結(jié)果丟失,具體細(xì)節(jié)問(wèn)題請(qǐng)參考下本文
    2021-06-06
  • Linux安裝單機(jī)版Redis的完整步驟

    Linux安裝單機(jī)版Redis的完整步驟

    這篇文章主要給大家介紹了關(guān)于Linux安裝單機(jī)版Redis的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • Redis安裝使用RedisJSON模塊的方法

    Redis安裝使用RedisJSON模塊的方法

    在使用Redis中,我們可以使用大量的Redis模塊來(lái)擴(kuò)展Redis的功能,本文主要介紹了Redis安裝使用RedisJSON模塊的方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-03-03
  • Redis list 類型學(xué)習(xí)筆記與總結(jié)

    Redis list 類型學(xué)習(xí)筆記與總結(jié)

    這篇文章主要介紹了Redis list 類型學(xué)習(xí)筆記與總結(jié),本文著重講解了關(guān)于List的一些常用方法,比如lpush 方法、lrange 方法、rpush 方法、linsert 方法、 lset 方法等,需要的朋友可以參考下
    2015-06-06

最新評(píng)論