Redis之序列化POJO

2021-09-08 11:59:57 字數 3061 閱讀 5195

redis儲存方式有很多種,但是我個人覺得最好用的並非是string儲存型別,而是hash儲存型別,如果在使用redis的時候單純的只使用到string儲存型別的話,我個人覺得完全體現不了redis的特性。

redis 是乙個key-value資料庫,但在我看來他並不是單純的key-value資料庫,因為他相對於其他同型別的nosql資料來講,redis提供了更多資料型別儲存格式。比如如果需要使用nosql型別的資料庫作為應用的快取,我相信memcached比redis更適合,但是現實中往往很多人使用redis就僅僅只是使用string型別來做快取。

redis有hash型別的value儲存資料格式,不知道說到這裡,大家有沒有想到我們傳統的關係型資料的資料儲存格式。

其實我一直都想把redis做成乙個應用與傳統關係型資料庫之間的媒介,從而實現盡量在高負載的環境下減少資料庫的io,並實現資料庫持久化,且能夠更好的實現非同步與傳統資料庫的資料同步。

hash

常用命令:

hget,hset,hgetall 等。

應用場景:

我們簡單舉個例項來描述下hash的應用場景,比如我們要儲存乙個使用者資訊物件資料,包含以下資訊:

使用者id為查詢的key,儲存的value使用者物件包含姓名,年齡,生日等資訊,如果用普通的key/value結構來儲存,主要有以下2種儲存方式:

第一種方式將使用者id作為查詢key,把其他資訊封裝成乙個物件以序列化的方式儲存,這種方式的缺點是,增加了序列化/反序列化的開銷,並且在需要修改其中一項資訊時,需要把整個物件取回,並且修改操作需要對併發進行保護,引入cas等複雜問題。

第二種方法是這個使用者資訊物件有多少成員就存成多少個key-value對兒,用使用者id+對應屬性的名稱作為唯一標識來取得對應屬性的值,雖然省去了序列化開銷和併發問題,但是使用者id為重複儲存,如果存在大量這樣的資料,記憶體浪費還是非常可觀的。

那麼redis提供的hash很好的解決了這個問題,redis的hash實際是內部儲存的value為乙個hashmap,並提供了直接訪問這個map成員的介面,如下圖:

也就是說,key仍然是使用者id, value是乙個map,這個map的key是成員的屬性名,value是屬性值,這樣對資料的修改和訪問都可以直接通過其內部map的key(redis裡稱內部map的key為field), 也就是通過 key(使用者id) + field(屬性標籤) 就可以操作對應屬性資料了,既不需要重複儲存資料,也不會帶來序列化和併發修改控制的問題。很好的解決了問題。

hash操作對應資料庫的表資料儲存方式其實是一樣的,所以我們能夠很容易切入到redis中,並把傳統資料庫的表資料存入到redis的hash資料型別中。這裡我需要跟大家分享的是如果快速的插入物件到redis中。

/**

* * @title: set

* @description: 儲存實體

儲存之後格式是:

獲取資料:

/**

* * @title: get

* @description: 根據redis 中物件的key 獲取物件資訊  想請請看entries()方法,connection.hgetall

以上介紹的是單個pojo的資料儲存於獲取,但是如果是大批量的資料,我們會不會也只是多次執行同乙個方法的方式去獲取物件集合的呢?答案是否定的,因為redis已經為我們提供了更好的處理方法pipelined  管道操作,意指多個資料統一返回。

/**

* * @title: listconn

* @description: 管道批量獲取物件集合 傳入物件的key  官方提供方法

上述方法會返回乙個結果集,但是我發現返回的結果集中序列化的屬性並沒有反序列化完全導致輸出出現亂碼,先看下springdataredis提供的反序列化方法:

@suppresswarnings()

private list deserializemixedresults(list rawvalues, redisserializer valueserializer, redisserializer hashkeyserializer, redisserializer hashvalueserializer)  list values = new arraylist(); for (object rawvalue : rawvalues)  else if (rawvalue instanceof list)  else if (rawvalue instanceof set && !(((set) rawvalue).isempty()))  else if (rawvalue instanceof map && !(((map) rawvalue).isempty()) && ((map) rawvalue).values().iterator().next() instanceof byte)  else  } return values; } serializationutils類: public static mapdeserialize(maprawvalues, redisserializerhashkeyserializer, redisserializerhashvalueserializer)  mapmap = new linkedhashmap(rawvalues.size()); for (map.entryentry : rawvalues.entryset())  return map; }

再看下我修改的之後的反串行話方法:

@suppresswarnings()

為什麼POJO類要實現序列化

1 序列化就是一種用來處理物件流的機制,所謂物件流就是將物件的內容進行流化。可以對流化後的物件進行讀寫操作,也可以在網路之間傳輸,需要實現serializable介面,該介面沒有需要實現的方法,只是為了表示物件是可以序列化的。序列化是將物件轉換為容易傳輸的格式的過程。2 是物件永久化的一種機制,在程...

Redis例項 序列化和反序列化

由於每個字串型別鍵只能儲存乙個字串,而一篇部落格文章是由標題 正文 作者與發布時間等多個元素構成的。為了儲存這些元素,我們需要使用序列化函式 如serialize 將它們轉換成乙個字串。除此之外,因為字串型別鍵可以儲存二進位制資料,所以也可以使用messagepack進行序列化,它的速度更好,占用空...

redis序列化器

redis和session共享牽扯到了序列化器,所以找了找資料 redis快取用到了序列化,如果是存string就不需要用到序列化,但是如果需要存bean物件和集合物件,就必須要轉序列化,這說幾種 jdkserializationredisserializer 這個是spring data redi...