【Redis錯誤】-Redis存、取異常之序列化問題
阿新 • • 發佈:2018-11-02
問題場景:因業務不斷擴充套件,實體類有較多的重複欄位,故要優化資料結構,從而優化系統性能,增加程式碼的可複用性。測試環境和預生產都沒有問題,到生產有部分欄位取不到數值,關了快取開關後,發現業務程式碼正常了,開啟快取就會出現各種null異常。
問題分析:Redis存進去的日誌正常,去的時候要麼少欄位,要麼整個結果集為null,本地測試,直接存完就取發現問題依舊如此。對比儲存String型別,發現Redis是可以正常存取的,那問題就出現在我們重構的實體類中,最後排查到新的實體類未被序列話造成的,如圖:
少實現了Serializable介面。
實現Serializable介面的意義:
對例項物件的狀態(State 物件屬性而不包括物件方法)進行通用編碼(如格式化的位元組碼)並儲存,以保證物件的完整性和可傳遞性,使其在不同時間或不同平臺的JVM之間共享例項物件。
檢視Redis原始碼:
public class RedisCache { private RedisInterface redisInterface; public <T> T get(String key) { byte[] data = redisInterface.get(SerializationUtils.serialize(key)); return (T) SerializationUtils.deserialize(data); } public void set(String key, final Object value) { redisInterface.set(SerializationUtils.serialize(key), SerializationUtils.serialize(value)); } public void set(String key, Object value, int expire) { set(key, value); expire(key, expire); } public void expire(String key, int expire) { redisInterface.expire(SerializationUtils.serialize(key), expire); } public void evict(String key) { redisInterface.del(SerializationUtils.serialize(key)); } public void setRedisInterface(RedisInterface redisInterface) { this.redisInterface = redisInterface; } }
再看其抽象工具類:
public abstract class SerializationUtils { /** * Serialize the given object to a byte array. * @param object the object to serialize * @return an array of bytes representing the object in a portable fashion */ public static byte[] serialize(Object object) { if (object == null) { return null; } ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); try { ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(object); oos.flush(); } catch (IOException ex) { throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex); } return baos.toByteArray(); } /** * Deserialize the byte array into an object. * @param bytes a serialized object * @return the result of deserializing the bytes */ public static Object deserialize(byte[] bytes) { if (bytes == null) { return null; } try { ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); return ois.readObject(); } catch (IOException ex) { throw new IllegalArgumentException("Failed to deserialize object", ex); } catch (ClassNotFoundException ex) { throw new IllegalStateException("Failed to deserialize object type", ex); } } }