現在的系統是越來越複雜了,不僅僅是功能複雜,系統結構也非常複雜,而且經常在一個系統裏包含幾種不同語言編寫的子系統。例如用 JavaScript 做前端開發、用 Java/PHP 等等做後端,C/C++/Go 等做一些底層模塊等等(我只是舉個栗子,不要挑起鬥爭哦)。
這些不同語言編寫的子系統經常需要進行一些交互,多數方面的數據交互一般都有對應的技術或者中間件來解決,例如消息中間件、數據庫、RESTful 接口、Redis 等等。
本文主要聚焦於緩存系統的交互。
在多語言開發的系統中,使用 Redis 這類服務實現緩存交付是非常適合的,但前提是緩存的數據必須是每一種語言都能識別。基於這個前提來考量,JSON、XML 是最合適的格式,因爲它們是語言無關的規範,任何語言都能方便的解析這兩種格式。而 JSON 相比 XML 又更優一些,因爲同樣數據用 JSON 表示體積更小。
所以 Redis + JSON 就成爲了跨語言環境中的緩存首先解決方案。不過我之前一直在強調單獨使用 Redis 做緩存的嚴重問題(詳情):巨大的緩存數據吞吐量會導致 Redis 的數據讀取變得異常緩慢,而擴容 Redis 的成本又非常高。
因此我們有必要在跨語言環境中使用 J2Cache 。
那麼問題來了,J2Cache 是一個 Java 開發的緩存橋樑,非 Java 語言的應用怎麼用 J2Cache 呢?答案是用不了!
但是可行!
我們假設一個系統中包含兩個應用,一個 Java 開發(J應用),另外一個隨便用什麼別的語言開發,例如 Python (P應用)?
J應用和 P應用之間需要進行緩存交互,在 J2Cache 中,兩個節點之間的數據交互包括:
- 緩存數據
- 消息通知
J2Cache 從 2.0 版本開始就是用 JSON 格式的消息通知,默認走 Redis 的 Pub/Sub 來傳播,因此 P應用只需要連接到 Redis 對應的 Pub/Sub 通道就可以獲取和發佈消息通知。
最大的問題是“緩存數據”,因爲應用系統中的緩存數據一般會比較複雜,例如我們會緩存一個對象、一個列表、數組等等。在 Java 應用中我們在將這些數據寫到 Redis 時一般是採用序列化的方式,而你讓其他語言來讀取 Java 序列化數據是很難,可以說是幾乎不可能的。
因此我們也必須用 JSON 的格式來表示我們所要緩存的數據,這樣就可以讓別的語言方便的解析數據。
在 J2Cache 中是需要配置 j2cache.serialization = json 即可實現這個需求。
J2Cache 使用的是 FST 庫提供的 JSON 序列化方案,來看看一個普通對象序列化後的結果:
首先是要序列化的類:
public class Person implements Serializable {
private String name;
private int age;
private BigInteger seconds = new BigInteger("100");
private List<School> schoolList;
private HashMap<String, Integer> jobs;
}
public class School implements Serializable {
private String name;
private int random = (int)(Math.random() * 1000);
}
初始化的數據:
person = new Person();
person.setName("Winter Lau");
person.setAge(19);
person.setSchoolList(Arrays.asList(new School("西北工業大學"), new School("泉州第五中學"), new School("城東中學"), new School("洛南小學")));
person.setJobs(new HashMap<String, Integer>(){{
put("creawor", 3);
put("moabc", 5);
put("huateng", 3);
put("oschina", 8);
}});
序列化的結果:
{"@type":"net.oschina.j2cache.Person","@object":{"age":19,"seconds":{"@type":"java.math.BigInteger","@object":[1,["byte",100]]},"create_time":{"@type":"date","@object":[1539737786400]},"jobs":{"@type":"map","@object":[4,"creawor",3,"huateng",3,"moabc",5,"oschina",8]},"schoolList":{"@type":"list","@object":[4,{"@type":"net.oschina.j2cache.School","@object":{"random":950,"name":"西北工業大學"}},{"@type":"net.oschina.j2cache.School","@object":{"random":983,"name":"泉州第五中學"}},{"@type":"net.oschina.j2cache.School","@object":{"random":647,"name":"城東中學"}},{"@type":"net.oschina.j2cache.School","@object":{"random":766,"name":"洛南小學"}}]},"name":"Winter Lau"}}
而消息通知的數據更爲簡單:
{"keys":[],"operator":1,"src":6160636}
所以,當我們用其他語言來編寫緩存操作的時候,只需要參考 J2Cache 的流程對這兩種 JSON 格式的數據進行解析即可。
有興趣的朋友可以根據本文的思路來開發不同語言版本的 J2Cache ,我之前已經開發了一個 Python 的版本的雛形 —— Py3Cache。
歡迎大家貢獻 https://gitee.com/ld/J2Cache