hazelcast的坑爹事

轉載自

http://blog.csdn.net/hengyunabc/article/details/18514563


簡介

開源中國的簡介:html

Hazelcast是一個高度可擴展的數據分發和集羣平臺。特性包括:java

  • 提供java.util.{Queue, Set, List, Map}分佈式實現。
  • 提供java.util.concurrency.locks.Lock分佈式實現。
  • 提供java.util.concurrent.ExecutorService分佈式實現。
  • 提供用於一對多關係的分佈式MultiMap。
  • 提供用於發佈/訂閱的分佈式Topic(主題)。
  • 經過JCA與J2EE容器集成和事務支持。
  • 提供用於安全集羣的Socket層加密。
  • 支持同步和異步持久化。
  • 爲Hibernate提供二級緩存Provider 。
  • 經過JMX監控和管理集羣。
  • 支持動態HTTP Session集羣。
  • 利用備份實現動態分割。
  • 支持動態故障恢復。

簡介是美好的,現實是坑爹的。node

優勢

先說下優勢吧:git

有個Manager Center的管理界面,很漂亮,能夠看到不少有用的數據。包括每一個Map的請求次數等。這些在Memcached,Redis上只能看個大概。github

簡單的配置很方便,能夠像JDK裏的Map,List同樣使用。spring


坑爹事情

配置各類找不到

有不少xml的配置方式沒有寫在文檔上,要到代碼裏各類找。友情提示,能夠到代碼裏的test目錄下找到比較完整的配置:緩存

https://github.com/hazelcast/hazelcast/blob/maintenance-3.x/hazelcast-spring/src/test/resources/com/hazelcast/spring/node-client-applicationContext-hazelcast.xml
安全

有不少參數的配置沒有寫在文檔上,要到代碼裏各類找。友情提示,在com.hazelcast.instance.GroupProperties 這個類裏找到一些在文檔上沒有的配置參數。網絡

默認的超時配置太長

不少超時配置都是上百秒的,試想如今的網站或者應用,有哪一個能夠忍受上百秒的超時。從另外一個側面也能夠看出hazelcast的本身的信心不足,要靠超長時間的超時來保證運行的正確性。app

即便配置了較短的超時時間,仍是有可能會有各類出人意料的超時,認真研究過代碼後,發現是有不少超時時間是在代碼裏寫死的。。

版本之間不兼容

版本之間不兼容,不能滾動升級。這就意味着,當升級時,整個集羣都要一塊重啓,這對不少網站來講,是不能忍受的。聽說從3.1版本後會保證小版本的兼容性。

https://github.com/hazelcast/hazelcast/issues/14

hazelcast裏代碼一大問題就是把序列化方案和網絡通信混在一塊兒了,致使各類升級兼容問題。每一個消息包在解析時,都有可能由於類有改動而不兼容。

並且序列化方案仍是那種要實現一個特定接口的。在Protobuf,Thrift,及各類基於反射的序列化方案這麼流行的今天,很難想像會有這樣難用的序列化方式。

一個結點出問題,影響整個集羣

當集羣裏某個節點出故障時,好比OOM,CPU100%,沒反應以後,集羣裏發到那個結點的操做就各類超時,各類不正常。這個能夠算是hazelcast的一個致命的缺點。

咱們線上的集羣有30多個結點,隨便一個有問題,都會致使整個集羣有問題。另外,當集羣裏有一個應用下線/上線,都會引發數據的遷移,儘管遷移是自動的,可是也是一個不可控的風險。

咱們開始時用的是hazelcast2.5.1,後來升級到3.1.3版本。升級後發現兩個結點間常常會有網絡流量超高的狀況,最後發現是merge-policy的配置在3.0只能配置類的全名,而在2.5是能夠配置一個簡稱的。而後在集羣裏有數據要遷移,進行Merge時,就會由於ClassNotFoundException而失敗。而Hazelcast坑爹的地方在於它不斷地重試,並且是無停頓地重試,從而致使兩個結點之間網絡流量超高,甚至超過了100Mbps。

hazelcast client很難用

首先,仍是文檔太少,不少配置根本沒有提到,得本身到代碼裏去找。

另外,若是hazelcast server集羣所有掛掉後,client竟然不會本身重連(重試3次就放棄了)。如今的各類組件重啓是很正常的事情,而hazelcast client竟然不會自動重連,真心使人無語。更加扯蛋的是,好比map.get,若是沒有鏈接上,會拋出一個RuntimeException,那麼整個線程都退出了。

3.0版本和3.0.2版本之間的配置格式竟然有很大的變化,不少時候,找個配置,得本身去看xml的xsd文件。。

結點之間Merge時,須要反序列化

這個我認爲是代碼太多致使的混亂。結點之間數據合併時,原本只要比較下數據的版本,時間等就能夠了,可是在合併時卻把對象反序化出來。若是在Server端沒有對應的jar包,則會拋出ClassNotFoundException。

參考這裏:

https://github.com/hazelcast/hazelcast/issues/1514


一些原理性的東東

Partition

從原理上來講,hazelcast是默認有271個partition,這271個parition平均分佈在集羣裏的結點中,所以集羣裏的數據分散在每一個結點中。而後在進行操做時,先計算獲得key所在的partiion,再進行操做。

詳細請參考PartitionServiceImpl這個類的代碼:

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. public final int getPartitionId(Data key) {  
  2.     int hash = key.getPartitionHash();  
  3.     return (hash != Integer.MIN_VALUE) ? Math.abs(hash) % partitionCount : 0;  
  4. }  

NearCache的實現原理

hazelcast裏有一個所謂的nearcache的東東,其實這個很簡單,就是一個本地的二級緩存。在get的時候先到本地的nearcache裏查找,若是沒有計算hash,再到對應的結點中取數據,再放到nearcache裏。

參考:

http://www.oschina.net/p/hazelcast

http://www.hazelcast.org/docs/3.1/manual/html-single/

相關文章
相關標籤/搜索