Redis序列化

1. 先從序列化說起

首先什么是序列化椿息,簡單地來說序列化就是將對象轉換成字節(jié)序列可训,反序列化就是將字節(jié)序列轉化成對象仓坞。

2. RedisTemplate

Redis作為項目中常用的緩存中間件帆阳,我們通常使用spring-data-redis中提供了RedisTemplate來操作Redis迎吵。而在初始化RedisTemplate需要進行設置key/value的序列化方式嗤形,那么我們應該如何設置對應的序列化方式精偿?

    @Bean(name = {"qualityRedisTemplate"})
    public RedisTemplate<String, Object> qualityRedisTemplate(JedisConnectionFactory qualityConFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        
        template.setConnectionFactory(qualityConFactory);
        template.setKeySerializer(jdkSerializationRedisSerializer);
        template.setValueSerializer(jdkSerializationRedisSerializer);
        return template;
    }

3. 序列化方式

spring-data-redis的序列方式是通過實現(xiàn)RedisSerializer接口,默認實現(xiàn)了6種序列化方式赋兵,分別是GenericToStringSerializer笔咽、Jackson2JsonRedisSerializer、JdkSerializationRedisSerializer霹期、OxmSerializer叶组、StringRedisSerializer、GenericJackson2JsonRedisSerializer历造。

image.png
3.1 JdkSerializationRedisSerializer

這種序列化方式是RedisTemplate默認的序列化方式甩十,使用這種序列化方式的前提:被序列化的對象必須實現(xiàn)了java.io.Serializable接口。這種方式序列化之后保存的是字節(jié)序列吭产,對于開發(fā)調(diào)試不太友好侣监,使用Redis客戶端打開都是亂碼的。

3.2 StringRedisSerializer

這種序列化方式是StringRedisTemplate默認的序列化方式臣淤。這種實現(xiàn)方式比較輕量級橄霉、效率比較高,但是這種方式只能對字符串進行序列化邑蒋,無法對普通對象進行序列化姓蜂。如果想對普通對象進行序列化按厘,必須先手動轉化成String格式。

3.3 GenericToStringSerializer

這種序列化方式與StringRedisSerializer非常相似钱慢,只能對八種基本類型進行序列化刻剥。如果對普通對象進行序列化必須另外實現(xiàn)ConversionService或者TypeConverter

3.4 Jackson2JsonRedisSerializer

這種序列化方式從名字就可以看出來是通過將對象序列化成json串進行存儲的滩字,這種存儲方式對于開發(fā)調(diào)試比較友好造虏,排查線上問題也更加方便。但是這種序列化方式麦箍,必須在構造序列化對象時傳入對象的類型漓藕,否則會導致反序列化錯誤。

3.5 GenericJackson2JsonRedisSerializer

這種序列化方式是對Jackson2JsonRedisSerializer的一種補充挟裂,也是將對象序列化成json串進行存儲享钞,序列化時將對象類型也保存了,所以反序列化時無需傳入對象類型诀蓉,這種實現(xiàn)方式顯然更好栗竖。

// 使用jackson或者genericJackson存在的坑
redisTemplate.opsForValue().set(key, 10L);
Long value = redisTemplate.opsForValue().get(key); 
// 此時獲得的值的類型為Integer類型, 直接進行強轉會進行報錯
// 其實這也不能說是序列化存在的問題,而是json的數(shù)字類型與java的數(shù)據(jù)類型不能兼容
3.6 OxmSerializer

這種序列化方式是通過將對象序列化成xml的格式進行存儲渠啤,使用xml存儲格式比較統(tǒng)一規(guī)范狐肢。但是序列化成xml與反序列化成對象,都是比較耗時的沥曹。

4. 對比序列化方式

序列化方式 序列化后大小 序列化時間 反序列化時間 可讀性
jdk 615 0.01 0.016
jackson 337 0.005 0.01
genericJackson 425 0.003 0.005
genericString 283 0.006 0.008
oxm 481 0.031 0.045 一般

注:序列化時間與反序列化時間是分別執(zhí)行100次得出的時間

    public void timeCost() {
        RedisSerializer redisSerializer = redisTemplate.getValueSerializer();
        LocalDateTime start = LocalDateTime.now();
        byte[] serialize = new byte[]{};
        for (int i = 0; i < 100; i++) {
            serialize = redisSerializer.serialize(activity);
        }
        LocalDateTime end = LocalDateTime.now();
        System.out.println("序列化耗時:" + Duration.between(start, end));
        start = LocalDateTime.now();
        for (int i = 0; i < 100; i++) {
            redisSerializer.deserialize(serialize);
        }
        end  = LocalDateTime.now();
        System.out.println("反序列化耗時:" + Duration.between(start, end));
    }

5. 使用中存在的坑

5.1 JdkSerializationRedisSerializer

// jdk序列化方式存在的坑
redisTemplate.opsForValue().set(key, 10);
redisTemplate.opsForValue().increment(key);  // 會拋出ERR value is not an integer or out of range 異常

5.2 Jackson2JsonRedisSerializer以及GenericJackson2JsonRedisSerializer

// 使用jackson或者genericJackson存在的坑
redisTemplate.opsForValue().set(key, 1L);
Long value = redisTemplate.opsForValue().get(key); 
// 此時獲得的值的類型為Integer類型, 直接進行強轉會進行報錯
// 其實這也不能說是序列化存在的問題份名,而是json的數(shù)字類型與java的數(shù)據(jù)類型不能兼容

6. 其他第三方實現(xiàn)的序列化方式

  • GenericFastJsonRedisSerializer
  • KryoRedisSerializer
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市妓美,隨后出現(xiàn)的幾起案子僵腺,更是在濱河造成了極大的恐慌,老刑警劉巖壶栋,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辰如,死亡現(xiàn)場離奇詭異,居然都是意外死亡贵试,警方通過查閱死者的電腦和手機琉兜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锡移,“玉大人呕童,你說我怎么就攤上這事∠海” “怎么了夺饲?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我往声,道長擂找,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任浩销,我火速辦了婚禮贯涎,結果婚禮上,老公的妹妹穿的比我還像新娘慢洋。我一直安慰自己塘雳,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布普筹。 她就那樣靜靜地躺著败明,像睡著了一般。 火紅的嫁衣襯著肌膚如雪太防。 梳的紋絲不亂的頭發(fā)上妻顶,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音蜒车,去河邊找鬼讳嘱。 笑死,一個胖子當著我的面吹牛酿愧,可吹牛的內(nèi)容都是我干的沥潭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼寓娩,長吁一口氣:“原來是場噩夢啊……” “哼叛氨!你這毒婦竟也來了呼渣?” 一聲冷哼從身側響起棘伴,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屁置,沒想到半個月后焊夸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡蓝角,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年阱穗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片使鹅。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡揪阶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出患朱,到底是詐尸還是另有隱情鲁僚,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站冰沙,受9級特大地震影響侨艾,放射性物質發(fā)生泄漏。R本人自食惡果不足惜拓挥,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一唠梨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侥啤,春花似錦当叭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糠雨,卻和暖如春才睹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背甘邀。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工琅攘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人松邪。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓坞琴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逗抑。 傳聞我的和親對象是個殘疾皇子剧辐,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容