Hazelcast入门
7月,我寫了一個博客向Java開發人員介紹erlang,重點介紹了這兩種語言之間的一些異同。 erlang虛擬機具有許多令人印象深刻的內置功能,其中之一是它們獨立于位置并且可以互相通信。 這意味著可以通過編寫很少的代碼行在VM之間同步數據。 如果您有一個網絡集群的服務器都在做相同的事情,這真是個好消息。
您可能會爭辯說,即使JVM無法執行最基本的進程間通信,也可能缺少某些東西。 但是,Java卻持相反的觀點,它具有基本的VM,然后在需要時在其上分層放置不同的服務。 這是否正確只是一個見解,我將其作為未來博客的主題,因為Hazelcast Guys似乎已經解決了JVM之間相互交談的問題; 這是本博客的重點。
那么,什么是Hazelcast?
Hazelcast新聞稿是這樣的:“ Hazelcast( www.hazelcast.com )正在通過開放源代碼重塑內存數據網格。 Hazelcast提供了一個嵌入式庫,任何Java開發人員都可以在幾分鐘之內包含該庫,從而使他們能夠構建優雅而簡單的關鍵任務,事務性和萬億級內存應用程序。”
那么,這到底意味著什么?
好的,那只是營銷/公關障礙。 在現實生活中,什么是Hazelcast? 可以使用代碼簡潔地給出答案。 假設您正在編寫一個應用程序,并且需要一個Map<String,String>而在生產環境中,您將在集群中擁有多個應用程序實例。 然后編寫以下代碼:
HazelcastInstance instance = Hazelcast.newHazelcastInstance(); loggedOnUsers = instance.getMap("Users");…意味著由您的應用程序的一個實例添加到地圖的數據可用于您的應用程序的所有其他實例2
您可以從中得出幾點。 首先,Hazelcast節點是“無主節點”,這意味著它不是客戶端-服務器系統。 有一個集群領導者,默認情況下是集群中最老的成員,它負責管理數據在系統中的分布方式。 但是,如果該節點發生故障,則下一個最舊的節點將接管。
擁有一堆分布式的地圖,列表,隊列等,意味著一切都保存在內存中。 如果集群中的一個節點死亡,那么您就可以了,不會有數據丟失; 但是,如果多個節點同時死亡,那么您將遇到麻煩,并且由于系統沒有時間重新平衡自身,您將丟失數據。 不用說,如果整個集群都死了,那么您將遇到大麻煩。
那么,為什么Hazelcast是個好選擇?
場景
為了演示Hazelcast,請想象您正在編寫一個應用程序,在這種情況下,該應用程序由MyApplication類建模,然后有一個很大的用戶世界,由BigWideWorld類建模。 正如預期的那樣,來自BigWideWorld用戶登錄并注銷了您的應用程序。 您的應用程序非常受歡迎,并且您正在集群中運行它的多個實例,因此,當用戶登錄該應用程序的實例時,它將其詳細信息(由User類建模)存儲在Map以及Map的內容與您的應用程序其他實例保存的地圖同步。
POM配置
首先要做的是設置POM.xml,只有一個條目需要考慮:
<dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast</artifactId><version>3.1</version></dependency>編碼
BigWideWorld是代碼的起點,對于這么大的概念而言,這是一個很小的類。 它有一個方法nextUser() ,它從應用程序所有用戶的集合中隨機選擇下一個要登錄或注銷的用戶的名稱。
public class BigWideWorld { private static Random rand = new Random(System.currentTimeMillis()); private final Users users = new Users(); private final int totalNumUsers = users.size(); public String nextUser() { User user = users.get(rand.nextInt(totalNumUsers)); String name = user.getUsername(); return name; } }用戶集合由Users類管理。 這是一個示例代碼便捷類,其中包含許多硬編碼用戶的詳細信息。
public class Users { /** The users in the database */ private final User[] users = { new User("fred123", "Fred", "Jones", "fredj@a.com"), new User("jim", "Jim", "Jones", "jimj@a.com"), new User("bill", "Bill", "Jones", "bill@a.com"), new User("ted111", "Edward", "Jones", "tedj@a.com"), new User("annie", "Annette", "Jones", "annj@a.com"), new User("lucy", "Lucy", "Jones", "lucyj@a.com"), new User("jimj", "James", "Jones", "jimj@a.com"), new User("jez", "Jerry", "Jones", "fredj@a.com"), new User("will", "William", "Jones", "willj@a.com"), new User("shaz", "Sharon", "Jones", "shazj@a.com"), new User("paula", "Paula", "Jones", "pauj@a.com"), new User("leo", "Leonardo", "Jones", "leoj@a.com"), }; private final Map<String, User> userMap; public Users() { userMap = new HashMap<String, User>(); for (User user : users) { userMap.put(user.getUsername(), user); } } /** * The number of users in the database */ public int size() { return userMap.size(); } /** * Given a number, return the user */ public User get(int index) { return users[index]; } /** * Given the user's name return the User details */ public User get(String username) { return userMap.get(username); } /** * Return the user names. */ public Set<String> getUserNames() { return userMap.keySet(); } }此類包含一些數據庫類型的調用,例如get(String username)返回給定名稱的用戶對象,或者get(int index)返回數據庫中的給定用戶,或者size()返回數字。數據庫中的用戶數量。
用戶由User類描述; 一個簡單的Java bean:
public class User implements Serializable { private static final long serialVersionUID = 1L; private final String username; private final String firstName; private final String lastName; private final String email; public User(String username, String firstName, String lastName, String email) { super(); this.username = username; this.firstName = firstName; this.lastName = lastName; this.email = email; } public String getUsername() { return username; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String getEmail() { return email; } @Override public String toString() { StringBuilder sb = new StringBuilder("User: "); sb.append(username); sb.append(" "); sb.append(firstName); sb.append(" "); sb.append(lastName); sb.append(" "); sb.append(email); return sb.toString(); } }繼續討論博客的癥結所在,這就是MyApplication類。 本博客中的大多數代碼只是櫥窗裝飾,重要的代碼在MyApplication的構造函數中。 該構造包含兩行代碼。 第一個使用新的Hazelcast實例,而第二個使用該實例創建名稱空間為“ Users”的Map<String, User> 。 這就是所需的所有Hazelcast特定代碼。 其他方法: logon() , logout()和isLoggedOn()僅管理用戶。
使用簡單的Main類將以上所有內容捆綁在一起:
public class Main { public static void main(String[] args) throws InterruptedException { BigWideWorld theWorld = new BigWideWorld(); MyApplication application = new MyApplication(); while (true) { String username = theWorld.nextUser(); if (application.isLoggedOn(username)) { application.logout(username); } else { application.logon(username); } application.displayUsers(); TimeUnit.SECONDS.sleep(2); } } }此代碼創建BigWideWorld和MyApplication的實例。 然后,它無限循環地抓住下一個隨機用戶名。 如果用戶已經登錄,則該用戶注銷。 如果用戶未登錄,則該用戶登錄。然后將顯示已登錄的用戶,以便您查看正在發生的情況。
運行應用
構建應用程序后,打開終端并導航到project target/classes目錄。 然后輸入以下命令:
java -cp /your path to the/hazelcast-3.1/lib/hazelcast-1.jar:. com.captaindebug.hazelcast.gettingstarted.Main運行時,您將獲得如下所示的輸出:
Logged on users: User: fred123 Fred Jones fredj@a.com User: jimj James Jones jimj@a.com User: shaz Sharon Jones shazj@a.com User: paula Paula Jones pauj@a.com User: lucy Lucy Jones lucyj@a.com User: jez Jerry Jones fredj@a.com User: jim Jim Jones jimj@a.com 7 -- 14:54:16-17接下來,打開更多終端并運行您的應用程序的更多實例。
如果您跟蹤輸出,則可以看到用戶登錄和注銷,并且每次更改都顯示用戶Map 。 一個應用程序的地圖更改反映在其他實例中的線索可能很難發現,但可以從地圖的總大小(輸出最后一行的第一個數字)中得出。 每次顯示地圖時,都會有一個用戶登錄或注銷。 但是,總大小可能會改變一個以上,這意味著其他實例的更改已影響您正在查看的地圖的大小。
因此,您有一個簡單的應用程序,當四個實例正在運行時,它們保持同步并知道哪些用戶已登錄。
它應該可以在大型群集中工作,但我從未嘗試過。 顯然,在大型集群中,您必須對配置文件進行一些改動,但這超出了本博客的范圍。
1好的,足夠的市場營銷能力。 總的來說,它確實是“有效的”,但是請記住,它是由像您和我這樣的開發人員編寫的軟件,它確實具有功能和特質 。 舉例來說,如果你還在使用2.4版本,然后立即升級。 這會有內存泄漏,這意味著它在感覺到時“只是默默地停止工作”。 最新版本是3.1。
2我選擇了Map作為示例,但對于其他集合類型(如List , Set和Queue也是如此,另外,Hazelcast還具有許多其他功能,這些功能超出了本博客的范圍,包括大量并發實用程序和發布/訂閱消息傳遞。
- 該博客的代碼可在github上找到: https : //github.com/roghughe/captaindebug/tree/master/hazelcast
翻譯自: https://www.javacodegeeks.com/2013/11/getting-started-with-hazelcast.html
總結
以上是生活随笔為你收集整理的Hazelcast入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mac电脑如何调整桌面图标的大小如何改变
- 下一篇: 所有其他指标均无用