Статьи

Начало работы с Hazelcast

В июле я написал блог , рассказывающий об эрланге разработчикам Java, рассказав о некоторых сходствах и различиях между двумя языками. Виртуальная машина Erlang имеет ряд впечатляющих встроенных функций, одна из которых заключается в том, что они не зависят от местоположения и могут общаться друг с другом. Это означает, что эти данные можно синхронизировать между виртуальными машинами, написав очень мало строк кода. Это действительно хорошая новость, если у вас есть сетевой кластер серверов, которые делают одно и то же.

Вы могли бы утверждать, что в JVM чего-то не хватает, если он не может даже выполнить самую основную межпроцессную связь; тем не менее, Java придерживается противоположного взгляда, у него есть базовая виртуальная машина, а затем она размещает различные сервисы сверху и по мере необходимости. Правильно ли это, это вопрос мнения, и я оставлю это как тему для будущего блога, потому что кажется, что Hazelcast Guys решили проблему JVM, разговаривающих друг с другом; что является точкой этого блога.

Итак, что такое Hazelcast?

Пресс-релиз Hazelcast выглядит примерно так: «Hazelcast ( www.hazelcast.com ) заново изобретает сетку данных в памяти через открытый исходный код. Hazelcast предоставляет встроенную библиотеку, которую любой разработчик Java может включить в считанные минуты, чтобы они могли создавать элегантно простые критически важные, транзакционные и терамалированные приложения в памяти ».

Итак, что это на самом деле означает?

Хорошо, так что это просто маркетинг / PR bumpf. Что такое Hazelcast … в реальной жизни? Ответ можно дать кратко, используя код. Представьте, что вы пишете приложение, и вам нужна Map<String,String> и когда вы работаете, у вас будет несколько экземпляров вашего приложения в кластере. Затем написание следующего кода:

1
2
    HazelcastInstance instance = Hazelcast.newHazelcastInstance();
    loggedOnUsers = instance.getMap("Users");

… Означает, что данные, добавленные на вашу карту одним экземпляром вашего приложения, доступны для всех остальных экземпляров вашего приложения 2

Из этого вы можете сделать несколько выводов. Во-первых, узлы Hazelcast «без хозяина», что означает, что это не система клиент-сервер. Есть лидер кластера, который по умолчанию является самым старым членом кластера, который управляет распределением данных по системе; однако, если этот узел вышел из строя, то вступит в действие следующий самый старый.

Наличие множества распределенных карт, списков, очередей и т. Д. Означает, что все хранится в памяти. Если один узел в вашем кластере умирает, тогда вы в порядке, нет потери данных; однако, если несколько узлов погибают одновременно, у вас возникнут проблемы, и вы потеряете данные, так как система не успеет восстановить баланс. Также само собой разумеется, что если весь кластер умрет, то у вас большие проблемы.

Итак, почему Hazelcast хорошая ставка?

  1. Это с открытым исходным кодом. Обычно это хорошая вещь …
  2. Hazelcast только что получил крупную денежную инъекцию, чтобы «коммодитизировать» продукт. Подробнее об этом смотрите здесь и здесь .
  3. Род Джонсон, да, мистер Спринг, теперь входит в правление Hazelcast.
  4. Это просто работает 1 .
  5. Начать довольно легко.

Сценарий

Чтобы продемонстрировать Hazelcast, представьте, что вы пишете приложение, в данном случае смоделированное классом MyApplication а затем существует большой, широкий мир пользователей, смоделированный классом BigWideWorld . Как и ожидалось, пользователи из BigWideWorld входят и выходят из вашего приложения. Ваше приложение очень популярно, и вы запускаете несколько его экземпляров в кластере, поэтому, когда пользователь регистрирует экземпляр приложения, он сохраняет свои данные (как смоделировано классом User ) на Map и содержимое карты. синхронизируются с картами, хранящимися в других экземплярах вашего приложения.

Снимок экрана 2013-10-21 в 20.45.28

Конфигурация POM

Первое, что нужно сделать, — это настроить файл POM.xml, и нужно учесть только одну запись:

1
2
3
4
5
<dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast</artifactId>
        <version>3.1</version>
    </dependency>

Код

BigWideWorld является отправной точкой для кода, и это очень маленький класс для такой большой концепции. У него есть один метод, nextUser() , который случайным образом выбирает имя следующего пользователя для входа или выхода из коллекции всех пользователей вашего приложения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
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 . Это пример удобства класса кода, который содержит ряд жестко запрограммированных данных пользователей.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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-бин:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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, а второй использует этот экземпляр для создания Map<String, User> с пространством имен «Users». Это весь код Hazelcast, который необходим. Другие методы: logon() , logout() и isLoggedOn() просто управляют пользователями.

Все вышеперечисленное связывается с помощью простого класса Main :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 . Затем он бесконечно зацикливается, захватывая следующее случайное имя пользователя. Если пользователь уже вошел в систему, то он выходит из системы. Если пользователь не вошел в систему, то пользователь войдет в систему. После этого отобразятся зарегистрированные пользователи, чтобы вы могли видеть, что происходит.

Запуск приложения

После создания приложения откройте терминал и перейдите в каталог target/classes проектов. Затем введите следующую команду:

1
java -cp /your path to the/hazelcast-3.1/lib/hazelcast-1.jar:. com.captaindebug.hazelcast.gettingstarted.Main

При запуске вы получите вывод, который выглядит примерно так:

1
2
3
4
5
6
7
8
9
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 пользователя. Подсказка, что изменения в карте одного приложения отражаются в других экземплярах, может быть трудно обнаружить, но может быть выведена из общего размера карты (первое число в последней строке выходных данных). Каждый раз, когда отображается карта, один пользователь либо входил в систему, либо выходил из нее; однако общий размер может измениться более чем на один, что означает, что изменения других экземпляров повлияли на размер просматриваемой карты.

Снимок экрана 2013-10-21 в 22.22.21

Итак, у вас есть простое приложение, которое при запуске четырех экземпляров синхронизируется и знает, какие пользователи вошли в систему.

Он должен работать в больших кластерах, но я никогда не пробовал. По-видимому, в больших кластерах вам нужно выполнить некоторые jiggery-pokery с файлом конфигурации, но это выходит за рамки этого блога.

+1 Ладно, хватит о маркетинге говорить. В целом, это «просто работает», но помните, что это программное обеспечение, написанное разработчиками, такими как вы и я, имеет свои особенности и особенности . Например, если вы все еще используете версию 2.4, обновите сейчас . Это приводит к утечке памяти, что означает, что он «просто тихо перестает работать», когда ему это нравится. Последняя версия 3.1.

2 Я выбрал Map в качестве примера, но это также верно для других типов коллекций, таких как List , Set и Queue , плюс Hazelcast имеет много других функций, которые выходят за рамки этого блога, включая набор утилит для параллелизма и публикации / подписки обмена сообщениями.

Ссылка: Начало работы с Hazelcast от нашего партнера по JCG Роджера Хьюза в блоге Captain Debug’s Blog .