Hazelcast 是由Hazelcast公司開發的一款開源的分布式內存級別的緩存資料庫,可以為基於JVM環境運行的各種應用提供分布式集群和分布式緩存服務。
利用Hazelcast可以滿足「分布式」、「集群服務」、「網格式內存數據」、「分布式緩存「、「彈性可伸縮服務」等的要求。
Hazelcast提供了對很多 java 接口的分布式實現,如Map, Queue, ExecutorService, Lock以及 JCache。它以一個 JAR 包的形式提供服務,並且提供了 Java, C/C++, .NET 以及 REST 客戶端。
在應用時,可以將Hazelcast的jar包直接嵌入到任何使用Java、C++、.NET開發的產品中,我們只需要在應用中引入一個jar包,進行簡單的配置和編碼就可以實現。
目前Hazelcast已經更新到3.X版本。
Hazelcast 分為開源版和商用版,開源版本遵循 Apache License 2.0 開源協議可以免費使用,商用版本需要獲取特定的License。兩者之間最大的區別在於:商用版本提供了數據的高密度存儲。
我們知道在JVM中,有自己特定的GC機制,無論數據是在堆中還是棧中,只要發現無效引用的數據塊,就有可能被回收。而Hazelcast的分布式數據都存放在JVM的內存中,頻繁的讀寫數據會導致大量的GC開銷。使用商業版的Hazelcast會擁有高密度存儲的特性,大大降低JVM的內存開銷,從而降低GC開銷。
Hazelcast 沒有任何中心節點(每個節點都是可以運行在任意伺服器的獨立JVM),在運行的過程中,它自己選定集群中的某個節點作為中心點來管理所有的節點。
Hazelcast 的數據是分布式存儲的。它會儘量將數據存儲在需要使用該項數據的節點上,以實現數據去中心化的目的。
在傳統的數據存儲模型中(MySql、MongDB、Redis等),數據都是獨立於應用單獨存放的,當需要提升資料庫的性能時,需要不斷加固單個資料庫應用的性能。
即使現在大量的資料庫已經可以支持集群模式或讀寫分離,但是基本思路都是某幾個庫支持寫入數據,其他的庫不斷的拷貝更新數據副本。這樣做的壞處一是會產生大量髒讀的問題,二是會消耗大量的資源來傳遞數據——從數據源頻繁讀寫數據會耗費額外資源,當數據量增長或創建的主從服務越來越多時,這個消耗呈指數級增長。
使用 Hazelcast 可以有效的解決數據中心化問題,它將數據分散的存儲在每個節點中,節點越多越分散。每個節點都有各自的應用服務,而Hazelcast集群會根據每個應用的數據使用情況分散存儲這些數據,在應用過程中數據會儘量「靠近」應用存放。這些在集群中的數據共享整個集群的存儲空間和計算資源。
集群中的節點是無中心化的,每個節點都有可能隨時退出或隨時進入。因此,在集群中存儲的數據都會有一個備份(可以配置備份的個數,也可以關閉數據備份)。這樣的方式有點類似於 hadoop,某項數據存放在一個節點時,在其他節點必定有至少一個備份存在。當某個節點退出時,節點上存放的數據會由備份數據替代,而集群會重新創建新的備份數據。
Hazelcast 的所有功能只需引用一個jar包,除此之外,它不需要依賴任何第三方包。因此可以非常便捷高效的將其嵌入到各種應用伺服器中,而不必擔心帶來額外的問題(jar包衝突、類型衝突等)。它僅僅提供一系列分布式功能,而不需要綁定任何框架來使用,因此適用於任何場景。
Hazelcast 還支持伺服器/客戶端模型,支持腳本管理、能夠和 Docker 快速整合等。
總的來說在獨立JVM中經常使用的數據結果或模型,Hazelcast 都提供了分布式集群的實現。
Hazelcast 提供了 Map、Queue、MultiMap、Set、List、Semaphore、Atomic 等常用接口的分布式實現。
以Map接口為例,當我們通過Hazelcast創建一個Map實例後,我們在節點A調用 Map::put(&34;,&34;) 方法添加數據,然後可以在節點B使用 Map::get(&34;) 獲取到值為&34; 的數據。
由於Hazelcast 服務之間是端對端的,沒有主從之分,集群中所有的節點都存儲等量的數據以及進行等量的計算。
Hazelcast 默認情況下把數據存儲在 271 個區上,這個值可以通過系統屬性 hazelcast.partition.count來配置。
對於一個給定的鍵,在經過序列化、哈希並對分區總數取模之後能得到此鍵對應的分區號,所有的分區等量的分布與集群中所有的節點中,每個分區對應的備份也同樣分布在集群中。
也就是說 Hazelcast 會使用哈希算法對數據進行分區,比如對於一個給定的map中的鍵,或者topic和list中的對象名稱,分區存儲的過程如下:
Hazelcast通過分片來存儲和管理所有進入集群的數據,採用分片的方案目標是保證數據可以快速被讀寫、通過冗餘保證數據不會因節點退出而丟失、節點可線性擴展存儲能力。下面將從理論上說明Hazelcast是如何進行分片管理的。
Hazelcast的每個數據分片(shards)被稱為一個分區(Partitions)。分區是一些內存段,根據系統內存容量的不同,每個這樣的內存段都包含了幾百到幾千項數據條目,默認情況下,Hazelcast會把數據劃分為271個分區,並且每個分區都有一個備份副本。當啟動一個集群成員時,這271個分區將會一起被啟動。
下圖展示了集群只有一個節點時的分區情況。
從一個節點的分區情況可以看出,當只啟動一個節點時,所有的271個分區都存放在一個節點中。
然後我們啟動第二個節點,會出現下面這樣的集群分區方式。
其中黑色的字體表示分區,藍色的字體表示備份。節點1存儲了標號為1到135的分區,這些分區會同時備份到節點2中。而節點2則存儲了136到271的分區,並備份到了節點1中。
此時如果再添加2個新的節點到集群中,Hazelcast會一個一個的移動分區和備份到新的節點中,使得集群數據分布平衡。
注意:
實際中分區並不是有序的分布,而是隨機分布,上面的示例只是為了方便理解,重要的是理解 Hazelcast 的平均分布分區以及備份。
集群中最老的節點(或者說最先啟動)負責定時發送分區表到其他節點,這樣如果有其他節點加入或者離開集群,所有的節點也能更新分區表。
這個定時任務時間間隔可以通過系統屬性 hazelcast.partition.table.send.interval來配置,預設值為15秒。
重分區會發生在:
此時最老節點會更新分區表,然後分發,再接著集群開始移動分區,或者從備份恢復分區。
如果最老的節點掛了,次老節點會接手這個任務。
有兩種方式,嵌入式和客戶端伺服器。
轉自:知乎一一哥