Привет! Меня зовут Денис Макаров, я бэкенд-тимлид в KTS.

В прошлый раз мы сравнили Tarantool с Redis, а в этой статье решили провести тесты с Hazelcast. Исследование проводили с коллегой, нашим бэкенд-разработчиком и автором блога Линой Костян.

Денис Макаров

Бэкенд-тимлид

Лина Костян

Бэкенд-разработчик

Так же, как в прошлой статье, мы рассматриваем вариант Tarantool как замены: берём типичные кейсы работы с Hazelcast и реализуем такие же механики на Tarantool.

Выводы из нашего исследования можно прочесть в конце статьи.

Для тестирования брали Grafana K6 — инструмент для нагрузочного тестирования, который позволяет создавать и запускать тестовые сценарии на JavaScript и анализировать результаты тестирования. Он имеет широкий набор функций для создания тестовых сценариев и может работать с различными протоколами, такими как HTTP, WebSocket, gRPC и т.д. 

Grafana K6 можно использовать как в командной строке, так и в интерфейсе Grafana. Удобной особенностью K6 является возможность подключать сторонние расширения для работы с протоколами, которые изначально не поддерживаются К6. Так, из коробки К6 не умеет работать с Tarantool, поэтому мы использовали расширение xk6-tarantool.

Для работы с Hazelcast нам пришлось написать собственный плагин, ознакомиться с которым можно по ссылке. Для подключения необходимо пересобрать исполняемый файл К6 с использованием исходного кода нужных дополнений.

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

За время тестирования мы рассмотрели 6 сценариев:

Сценарии 1-5 выполнялись на виртуальной машине со следующими характеристиками: Ubuntu, 4CPU, 16GB RAM, 30GB SSD.

Сценарий 6 выполнялся на двух виртуальных машинах Ubuntu, 4CPU 16GB RAM, 30GB SSD.

Все сценарии выполнялись с профилем нагрузки в 100 виртуальных пользователей, длительностью 120 секунд.

Сценарий 1: key-value c операциями set/get/delete

Используем SET/GET/DEL команды в Hazelcast и аналоги в Tarantool.

Hazelcast:
Дефолтная конфигурация

Tarantool:
Дефолтная конфигурация
Спейс с полями (key string, value string)

???? Hazelcast

Код сценариев k6
import hazelcast from "k6/x/hazelcast";
import exec from "k6/execution";

export const options = {
    discardResponseBodies: true,
    scenarios: {
        test: {
            executor: "constant-vus",
            exec: "set_keys",
            vus: 100,
            duration: "120s",
        },
        test: {
            executor: "constant-vus",
            exec: "get_keys",
            vus: 100,
            duration: "120s",
        },
        test: {
            executor: "constant-vus",
            exec: " del_keys",
            vus: 100,
            duration: "120s",
        },
    },
};


const client = hazelcast.connect([“host:port”]);

const map = hazelcast.getMap(client, "test");

export function set_keys() {
    hazelcast.set(map, exec.vu.iterationInInstance + exec.vu.idInInstance * 100, exec.vu
        .iterationInInstance + exec.vu.idInInstance * 1000);
}
export function get_keys() {
    hzCast.get(map, exec.vu.iterationInInstance + exec.vu.idInInstance * 100);
}

export function del_keys() {
    hazelcast.del(map, exec.vu.iterationInInstance + exec.vu.idInInstance * 100);
}

Сценарии set_keys, get_keys, del_keys запускались последовательно. 

Результаты выполнения сценариев

Время выполнения запросов

Avg

Min

Med

Max

p(90)

p(95)

Set_keys

5.1ms

105.61µs

3.55ms

85.24ms 

11.59ms

11.15ms

Get_keys

3.86ms

81.02µs

2.75ms

206.83ms 

8.63ms

11.15ms

Del_keys

3.79ms

80.64µs

2.72ms

74.16ms

8.43ms

10.87ms

Среднее RPS

Set_keys

19509

Get_keys

25736

Del_keys

26170

???? Tarantool

Скрипт инициализации
import tarantool from "k6/x/tarantool";
import exec from 'k6/execution';

const conn = tarantool.connect(“host:port”);
export const options = {
    discardResponseBodies: true,
    scenarios: {
        set: {
            executor: 'constant-vus',
            exec: 'set',
            vus: 100,
            duration: '120s',
        },
        get: {
            executor: 'constant-vus',
            exec: 'get',
            vus: 100,
            duration: '120s',
        },
        del: {
            executor: 'constant-vus',
            exec: 'del',
            vus: 100,
            duration: '120s',
        },
    },
};

export function set() {
    tarantool.replace(conn, "test", [exec.vu.iterationInInstance + exec.vu.idInInstance * 100, (exec.vu.iterationInInstance + exec.vu.idInInstance * 100).toString()])
};
export function get() {
    tarantool.call(conn, "box.space.test:select", [exec.vu.iterationInInstance + exec.vu.idInInstance * 100])
};
export function del() {
    tarantool.call(conn, "box.space.test:delete", [exec.vu.iterationInInstance + exec.vu.idInInstance * 100])

};

Сценарии set_keys, get_keys, del_keys запускались последовательно. 

Результаты выполнения сценариев

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

4.14ms

122.3µs

3.21ms

60.34ms

8.31ms

10.85ms

Get_keys

3.17ms

89.51µs

2.58ms

71.09ms

5.69ms

7.85ms

 

Del_keys

3.46ms

114.76µs

2.74ms

61.46ms

6.38ms

8.84ms

Среднее RPS

Set_keys

26813

Get_keys

33250

Del_keys

30873

Сравнительная  таблица по RPS

Hazelcast

Tarantool

Set_keys

19509

26813

Get_keys

25736

33250

Del_keys

26170

30873

Сравнительная таблица по медиане и перцентилям времени выполнения запросов

Hazelcast

Tarantool

med

p(90)

p(95)

med

p(90)

p(95)

Set_keys

3.55ms

11.59ms

11.15ms

3.21ms

8.31ms

10.85ms

Get_keys

2.75ms

8.63ms

11.15ms

2.58ms

5.69ms

7.85ms

 

Del_keys

2.72ms

8.43ms

10.87ms

2.74ms

6.38ms

8.84ms

Вывод

Tarantool производительнее на несколько тысяч rps в операциях записи, чтения и удаления.


Сценарий 2. Счётчик

Используем Increment и Decrement операции в счетчике в Hazelcast и аналогичные update операции в Tarantool.

Сценарии incr и decr выполняются параллельно. 

Hazelcast:
Дефолтная конфигурация

Tarantool:
Дефолтная конфигурация
Создаём спейс с полями (key string, value integer)

???? Hazelcast

Код сценариев к6
import hazelcast from "k6/x/hazelcast";
import exec from "k6/execution";

export const options = {
    discardResponseBodies: true,
    scenarios: {
        test_incr: {
            executor: 'constant-vus',
            exec: 'incr',
            vus: 100,
            duration: '120s',
        },
        test_decr: {
            executor: 'constant-vus',
            exec: 'decr',
            vus: 100,
            duration: '120s',
        },
    },
};

const client = hazelcast.connect([“host:port”]);

export function incr() {
    hazelcast.incr(client,'aa'+exec.vu.idInInstance);
}
export function decr() {
    hazelcast.decr(client,'aa'+exec.vu.idInInstance);
}

Результаты выполнения сценариев

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

INCR/DECR

6.98ms

69.04µs

5.26ms

131.56ms 

15.36ms 

18.94ms

Среднее RPS

INCR/DECR

28533

???? Tarantool

Скрипт инициализации tarantool
box.cfg{listen="127.0.0.1:3301"}
box.schema.space.create("test2")
box.space.test2:format({{name="name", type="string"}, {name="value", type="integer"}})
box.space.test2:create_index("primary", {parts={"name"}})

Код сценария к6
import tarantool from "k6/x/tarantool";
import exec from 'k6/execution';


const conn = tarantool.connect("host:port");
export const options = {
   discardResponseBodies: true,
   scenarios: {
       incr: {
           executor: 'constant-vus',
           exec: 'decr',
           vus: 100,
           duration: '120s',
       },
       decr: {
           executor: 'constant-vus',
           exec: 'decr',
           vus: 100,
           duration: '120s',
       },
   },
};
export function setup() {
   for (let i = 1; i < 101; i++) {
       tarantool.replace(conn, "test2", [i.toString(), 0]);
     }
  
 };
export function incr() {
   tarantool.call(conn, "box.space.test2:update", [exec.vu.idInInstance.toString(), [["+", 2, 1]]])
}
export function decr() {
   tarantool.call(conn, "box.space.test2:update", [exec.vu.idInInstance.toString(), [["-", 2, 1]]])
   }

Результаты выполнения сценариев

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

INCR/DECR

3.06ms

100.01µs

2.51ms

72.29ms

5.26ms 

7.05ms

Среднее RPS

INCR/DECR

32552

Сравнительная  таблица по RPS

Hazelcast

Tarantool

INCR/DECR

28533

32552

Сравнительная таблица по медиане и перцентилям времени выполнения запросов

Hazelcast

Tarantool

med

p(90)

p(95)

med

p(90)

p(95)

INCR/DECR

5.26ms

15.36ms 

18.94ms

2.51ms

5.26ms 

7.05ms

Вывод

Tarantool несколько производительнее и быстрее в операциях incr/decr.


Сценарий 3. Работа с множествами

Используем set и get для multimap... и реализовываем аналогичные возможности в Tarantool.

Hazelcast:
Дефолтная конфигурация

Tarantool:
Дефолтная конфигурация
Создаём спейс kv с полями (key string, element string)

???? Hazelcast

Код сценариев к6
import hazelcast from "k6/x/hazelcast";
import exec from "k6/execution";

export const options = {
    discardResponseBodies: true,
    scenarios: {
        test: {
            executor: "constant-vus",
            exec: "set_keys",
            vus: 100,
            duration: "120s",
        },
    },
};


const client = hazelcast.connect([“host:port”]);

const map = hazelcast.getMultimap(client, "multi_test");

export function set_keys() {
    hazelcast.multimapSet(map, 'test'+exec.vu.idInInstance*1000, exec.vu.iterationInInstance + exec.vu.idInInstance * 100, exec.vu
        .iterationInInstance + exec.vu.idInInstance * 1000);
}
export function get_keys() {
    hazelcast.multimapMembers(map, exec.vu.iterationInInstance + exec.vu.idInInstance * 100);
}

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

5.74ms

112.09µs

3.91ms 

127.62ms

13.09ms

17.16ms

Get_keys

4.11ms

80.38µs

2.85ms

144.19ms 

9.22ms

12.07ms

Среднее RPS

Set_keys

17301

Get_keys

24132

???? Tarantool

Скрипт инициализации
box.cfg{listen="127.0.0.1:3301"}
box.schema.space.create("test3")
box.schema.sequence.create('S',{min=1, start=1})
box.space.test4:format({{name="id", type="unsigned"},{name="name", type="string"}, {name="value", type="string"}})
box.space.test4:create_index("primary", {sequence='S', parts={"id"}})
box.space.test4:create_index("name", {unique=false, parts={"name"}})

Сценарий к6
import tarantool from "k6/x/tarantool";
import exec from 'k6/execution';


const conn = tarantool.connect(“host:port”);
export const options = {
    discardResponseBodies: true,
    scenarios: {
        add: {
            executor: 'constant-vus',
            exec: 'add',
            vus: 100,
            duration: '120s',
        },
        members: {
            executor: 'constant-vus',
            exec: 'members',
            vus: 100,
            duration: '120s',
        },
    },
};


export function add() {
    tarantool.insert(conn, "test3", [null, (exec.vu.idInInstance*1000).toString(), (exec.vu.iterationInInstance + exec.vu.idInInstance * 100).toString()])
}
export function members() {
    tarantool.call(conn, "box.space.test3.index.name:select", [(exec.vu.idInInstance*1000).toString()])
}

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

4.45 ms

126.08 µs

3.47ms

73.07 ms

8.93ms

11.73ms

Get_keys

3.34 ms

104.19 µs

2.71ms

73.04 ms

5.98 ms

8.33 ms

Среднее RPS

Set_keys

22355

Get_keys

29766

Сравнительная  таблица по RPS

Hazelcast

Tarantool

Set_keys

17301

22355

Get_keys

24132

29766

Сравнительная таблица по медиане и перцентилям времени выполнения запросов

Hazelcast

Tarantool

med

p(90)

p(95)

med

p(90)

p(95)

Set_keys

3.91ms 

13.09ms

17.16ms

3.47ms

8.93ms

11.73ms

Get_keys

2.85ms

9.22ms

12.07ms

2.71ms

5.98ms

8.33ms

Вывод

При работе с множествами Tarantool производительнее на несколько тысяч RPS для операций добавления и чтения.


Сценарий 4. Работа с диском

Используем команды Set/Get/… и реализовываем аналогичные возможности в Tarantool. 

Тестируем Сценарий 1, меняя конфигурацию БД. Цель теста — определить производительность работы с диском Hazelcast vs Tarantool.

Hazelcast:
Для тестов меняем параметр persistence enabled (false, true) и fsync (false, true)

Tarantool:
Создаём спейс kv с полями (key string, element string). Для тестов меняем параметр wal_mode (none, write, fsync)

???? Hazelcast

Результаты выполнения сценариев persistence: true, fsync: true

Время выполнения запросов

Avg

Min

Med

Max

p(90)

p(95)

Set_keys

5.22ms

110.18µs

3.62ms

142.03ms 

11.88ms

15.45ms

Get_keys

3.8ms

77.36µs

2.71ms

67.69ms 

8.45ms

10.9ms

Del_keys

3.81ms

83.14µs

2.71ms

114.89ms

8.51ms

10.99ms

Среднее RPS

Set_keys

19051

Get_keys

26160

Del_keys

26042

persistence: true, fsync: false

Время выполнения запросов

Avg

Min

Med

Max

p(90)

p(95)

Set_keys

4.91ms

103.5µs

3.46ms

109.04ms 

11.07ms

14.39ms

Get_keys

3.72ms

78.58µs

2.65ms

103.97ms 

8.26ms

10.69ms

Del_keys

3.68ms

80.38µs

2.63ms

77.61ms

8.19ms

10.56ms

Среднее RPS

Set_keys

20233

Get_keys

26702

Del_keys

26947

persistence: false, fsync: false

Время выполнения запросов

Avg

Min

Med

Max

p(90)

p(95)

Set_keys

5.1ms

105.61µs

3.55ms

85.24ms 

11.59ms

11.15ms

Get_keys

3.86ms

81.02µs

2.75ms

206.83ms 

8.63ms

11.15ms

Del_keys

3.79ms

80.64µs

2.72ms

74.16ms

8.43ms

10.87ms

Среднее RPS

Set_keys

19509

Get_keys

25736

Del_keys

26170

???? Tarantool, результаты выполнения сценариев

wal_mode Write

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

3.78ms

117.33µs

2.94ms

53.07ms 

7.51ms

9.93ms

Get_keys

2.7ms

86.38µs

2.18ms

45.22ms

4.72ms

6.7ms

Del_keys

2.93ms

108.13µs

2.32ms

70.4ms

5.29ms

7.35ms

Среднее RPS

Set_keys

26813

Get_keys

33250

Del_keys

30873

wal_mode: None

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

3.82ms

76.2µs

2.2ms

41.77ms

7.85ms

10.36ms

Get_keys

3.28ms

95.29µs

2.66ms

57.78ms

5.9ms

8.23ms

Del_keys

2.9ms

87.79µs

2.32ms

56.83ms

5.17ms

7.25ms

Среднее RPS

Set_keys

26335

Get_keys

33017

Del_keys

34273

wal_mode: Fsync

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

4.14ms

122.3µs

3.21ms

60.34ms

8.31ms

10.85ms

Get_keys

3.17ms

89.51µs

2.58ms

71.09ms

5.69ms

7.85ms

 

Del_keys

3.46ms

114.76µs

2.74ms

61.46ms

6.38ms

8.84ms

Среднее RPS

Set_keys

25055

Get_keys

31342

Del_keys

28758

Сравнительная  таблица по RPS

Hazelcast

Tarantool

persistence: true, fsync: false

wal_mode Write

Set_keys

20233

26813

Get_keys

26702

33250

Del_keys

26947

30873

persistence: false, fsync: false

wal_mode: None

Set_keys

19509

26335

Get_keys

25736

33017

Del_keys

26170

34273

persistence: true, fsync: true

wal_mode: Fsync

Set_keys

19051

25055

Get_keys

26160

31342

Del_keys

26042

28758

Сравнительная таблица по медиане и перцентилям времени выполнения запросов

Hazelcast

Tarantool

persistence: true, fsync: false

wal_mode: write

med

p(90)

p(95)

med

p(90)

p(95)

Set_keys

3.46ms

11.07ms

14.39ms

2.94ms

7.51ms

9.93ms

Get_keys

2.65ms

8.26ms

10.69ms

2.18ms

4.72ms

6.7ms

Del_keys

2.63ms

8.19ms

10.56ms

2.32ms

5.29ms

7.35ms

persistence: false, fsync: false

wal_mode: None

Set_keys

3.55ms

11.59ms

11.15ms

3.28ms

7.85ms

10.36ms

Get_keys

2.75ms

8.63ms

11.15ms

2.66ms

5.9ms

8.23ms

Del_keys

2.72ms

8.43ms

10.87ms

2.32ms

5.17ms

7.25ms

persistence: true, fsync: true

wal_mode: fsync

Set_keys

3.62ms

11.88ms

15.45ms

3.21ms

8.31ms

10.85ms

Get_keys

2.71ms

8.45ms

10.9ms

2.58ms

5.69ms

7.85ms

 

Del_keys

2.71ms

8.51ms

10.99ms

2.74ms

6.38ms

8.84ms

Вывод

При любых конфигурациях использования диска Tarantool производительнее. В частности, даже в режиме полной персистентности Tarantool быстрее Hazelcast, работающего в режиме выключенного логирования (persistance: false).


Сценарий 5. Вторичные индексы

Kv в tarantool (id, value) со вторичным индексом на value.

В hazelcast со вторичным hash индексом на “this” .

???? Tarantool

Скрипт инициализации
box.cfg{listen="127.0.0.1:3301"}
box.schema.space.create("test5")
box.space.test6:format({{name="id", type="unsigned"}, {name="value", type="string"}})
box.space.test6:create_index("primary", {parts={"id"}})
box.space.test6:create_index("secondary", {parts={"value"}})

Результаты выполнения сценариев

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

3.43ms

112.54µs

2.68ms

48.15ms

6.63ms

8.96ms

Get_keys

2.73ms

82.87µs

2.21ms

56.86ms

4.78ms

6.7ms

Среднее RPS

Set_keys

29031

Get_keys

36382

???? Hazelcast

Скрипт инициализации
const map = hazelcast.getMap(client, "test");

hazelcast.addIndex(map,["this"], "value");

Результаты выполнения сценариев

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

5.13ms

99.21µs

3.52ms

204.68ms 

11.62ms 

15.36ms

Get_keys

3.8ms

77.39µs

2.71ms

60.73ms

8.48ms 

10.95ms

Среднее RPS

Set_keys

19370

Get_keys

26126

Сравнительная  таблица по RPS

Hazelcast

Tarantool

Set_keys

19370

29031

Get_keys

26126

36382

Сравнительная таблица по медиане и перцентилям времени выполнения запросов

Hazelcast

Tarantool

med

p(90)

p(95)

med

p(90)

p(95)

Set_keys

3.52ms

11.62ms 

15.36ms

2.26ms

8.27ms

12.15ms

Get_keys

2.71ms

8.48ms 

10.95ms

1.86ms

6.32ms

9.41ms

Вывод

Оба приложения умеют работать со вторичными индексами «из коробки», однако Tarantool производительнее на несколько тысяч rps.


Сценарий 6. Влияние репликации на производительность

Тестируем сценарий 1, меняя конфигурацию репликации. Цель теста — определить влияние репликации на производительность БД.

Проводим 2 теста:

Сценарий 6.1 Hazelcast с master-master репликацией на 1 узел

Сценарий 6.2 Tarantool с master-slave репликацией на 1 узел

Сценарий 6.1 Hazelcast master-master

Результаты выполнения сценариев

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

3.78ms

643.85µs

2.91ms

74.92ms 

6.81ms

9.33ms

Get_keys

2.62ms

247.85µs

2ms

67.59ms

5.01ms 

6.74ms

Del_keys

2.6ms

236.8µs

1.98ms

115.51ms 

4.92ms

6.63ms

Среднее RPS

Set_keys

26322

Get_keys

37863

Del_keys

38155

Сценарий 6.2 Tnt-master-slave

Результаты выполнения сценариев

Время выполнения запросов

avg

min

med

max

p(90)

p(95)

Set_keys

4.35ms

129.16µs

3.32ms

72.58ms

8.83ms

11.61ms 

Get_keys

3.27ms

84.55µs

2.66ms

41ms

5.95ms

8.15ms

Del_keys

3.45ms

99.55µs

2.78ms

89.36ms

6.21ms

8.53ms

Среднее RPS

Set_keys

22883

Get_keys

30452

Del_keys

28830

Сравнительная  таблица по RPS

Hazelcast

Tarantool

Репликация на 1 узел (master-master)

Репликация на 1 узел (master-slave)

Set_keys

26322

22883

Get_keys

37863

30452

Del_keys

38155

28830

Сравнительная таблица по медиане и перцентилям времени выполнения запросов

Hazelcast

Tarantool

Репликация на 1 узел (master-master)

Репликация на 1 узел (master-slave)

med

p(90)

p(95)

med

p(90)

p(95)

Set_keys

2.91ms

6.81ms

9.33ms

3.32ms

8.83ms

11.61ms 

Get_keys

2ms

5.01ms 

6.74ms

2.2ms

4.67ms

6.46ms

Del_keys

1.98ms

4.92ms

6.63ms

6.21ms

8.53ms

6.21ms

Вывод

Hazelcast при репликации master-master работает быстрее, чем Tarantool в режиме master-slave.


Общие выводы из нагрузочного тестирования

Hazelcast

Hazelcast — это приложение Java без внешних зависимостей. Он предлагает те же интерфейсы и API, что и хорошо известный пакет java.util. Это позволяет комфортно работать с Hazelcast из Java-приложения. В отличие от Tarantool, поддерживает выполнение в нескольких потоках, что позволяет проще масштабировать приложение, но при этом несёт риски повреждения данных.

Tarantool

Документация. В отличие от Hazelcast, где часто встречаются устаревшие инструкции, у Tarantool более наглядная документация с примерами для актуальной версии.

SQL. Оба поддерживает SQL, но Tarantool ближе к привычной табличной организации данных, потому что поддерживает реляционную модель.

Сценарии 1, 2, 3 чаще встречаются в повседневной работе.

Сценарий 4 — режим персистентности.
Персистентность нужна для восстановления данных. Это in-memory решения, и при случайном завершении работы можно потерять все данные. Чтобы такого не произошло, необходимо логирование записей. В Tarantool и Hazelcast существуют разные режимы персистентности. По результатам теста Tarantool быстрее в режиме полной персистентности, чем Hazelcast вообще без персистентности. Это видно по сценарию 4. 

Сценарий 5 — вторичные индексы Tatantool быстрее в режиме key-value и при использовании вторичных индексов.
Вторичные индексы часто используются при проектировании структуры базы данных. В случае Tarantool это позволяет производить поиск не только по ключам, но и по значениям. 

Пример: у нас имеется таблица вида «табельный номер — ФИО сотрудника», где табельный номер является ключом. 

  • В Tarantool при создании вторичного индекса появляется возможность производить поиск не только по табельному номеру, но и по ФИО, что даёт возможность узнать табельный номер конкретного сотрудника

  • В Hazelcast тоже есть такая возможность, но производительность уступает Tarantool

Итоги. Tarantool оказался производительнее на запись и чтение и удаление в первых 5 сценариях. Если требуется полноценное решение для кэширования или хранения данных и взаимодействия с ними, которое можно использовать в качестве основной БД, рекомендуем присмотреться к Tarantool. Он ближе к привычной табличной организации данных, потому что поддерживает реляционную модель и запросы на SQL.

Совсем кратко:

Если не нужна репликация — берите Tarantool.

Для сценариев с репликацией сейчас выигрывает Hazelcast, но разница небольшая при других плюсах Тарантула.

Комментарии (0)