Thank you for reading this post, don't forget to subscribe!
Настройка master-master-master:
cat tarantool-stack.yml
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
version: '3.7' configs: app_lua: external: true x-tarantool-env: &tarantool-env TARANTOOL_REPLICATION_SOURCE: master@tarantool1:3301,master@tarantool2:3301,master@tarantool3:3301 TARANTOOL_MEMTX_MEMORY: 268435456 TARANTOOL_USER_NAME: master x-tarantool: &tarantool image: tarantool/tarantool:1.9.2 environment: <<: *tarantool-env deploy: replicas: 1 resources: limits: cpus: '0.30' memory: 256M restart_policy: condition: on-failure healthcheck: disable: true command: [ "tarantool" , "/opt/tarantool/app.lua"] networks: - tnt_cluster services: admin: restart: always image: "quay.io/basis-company/tarantool-admin" ports: - "8000:80" volumes: - ./tarantool-admin/php:/var/www/html/php - ./tarantool-admin/public/admin/js:/var/www/html/admin/js - ./tarantool-admin/public/admin/index.php:/var/www/html/admin/index.php - ./tarantool-admin/public/admin/style.css:/var/www/html/admin/style.css networks: - tnt_cluster tarantool1: <<: *tarantool configs: - source: app_lua target: /opt/tarantool/app.lua # volumes: # - ./app.lua:/opt/tarantool/app.lua # - tarantool1_cfg:/etc/tarantool/ # - tarantool1_data:/var/lib/tarantool tarantool2: <<: *tarantool configs: - source: app_lua target: /opt/tarantool/app.lua # volumes: # - ./app.lua:/opt/tarantool/app.lua # - tarantool2_cfg:/etc/tarantool/ # - tarantool2_data:/var/lib/tarantool tarantool3: <<: *tarantool configs: - source: app_lua target: /opt/tarantool/app.lua # volumes: # - ./app.lua:/opt/tarantool/app.lua #- tarantool3_cfg:/etc/tarantool/ networks: tnt_cluster: volumes: tarantool1_cfg: tarantool1_data: tarantool2_cfg: tarantool2_data: tarantool3_cfg: tarantool3_data: |
[/codesyntax]
В данном примере запускаются 3 сервиса tarantool c одной конфигурацией app_lua (в данном случае она external)
app.lua
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 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 |
box.cfg { log_level = tonumber(os.getenv("TARANTOOL_LOG_LEVEL")); replicaset_uuid = os.getenv("TARANTOOL_REPLICASET_UUID"); instance_uuid = os.getenv("TARANTOOL_INSTANCE_UUID"); memtx_max_tuple_size = 1048576 + 200; force_recovery = true; checkpoint_interval = 30; checkpoint_count = 3; } local log = require("log") local fiber = require("fiber") log.info("Info version %s", box.info.version) log.info("box.info.id %s", box.info.id) box.once( "schema", function() box.schema.space.create("test") box.space.test:create_index("primary", {unique = true, parts = {1, "integer"}}) end ) local testspace = box.space.test fiber_test_sleep = 0 fiber_test = fiber.create( function() while true do local status, call_res = pcall( function() local t = fiber.time64(); testspace:upsert({box.info.id, t}, {{"=", 2, t}}) end ) if not status then log.warn("call_res err %s", call_res) end fiber.testcancel() fiber.sleep(fiber_test_sleep) -- fiber.yield() end end ) |
[/codesyntax]
Для настройки Shard используется та же конфигурация
Здесь при инициализации создается БД test
Для настройки Shard используется та же конфигурация
Библиотека уровня приложения, которая обеспечивает сегментирование и надежную репликацию на стороне клиента для tarantool . Реализует однофазные и двухфазные протоколы операций (с поддержкой пакетной обработки), отслеживает доступность узлов и автоматически исключает отказавшие узлы из кластера.
Для разделения данных между узлами используется вариант согласованного хеширования.
- redundancy - коэффициент избыточности. Сколько копий каждого кортежа нужно хранить в кластере
- zone - зона резервирования. Может представлять одну машину или один центр обработки данных. Количество зон должно быть больше или равно коэффициенту избыточности: дублирование данных в одной зоне не увеличивает доступность.
К текущей конфигурации добавляем:
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
box.cfg{listen = 3301} box.schema.space.create('tester') box.space.tester:create_index('primary', {}) box.schema.user.create('test_user', {password = 'pass'}) box.schema.user.grant('test_user', 'read,write,execute', 'universe') console = require('console') cfg = { servers = { { uri = 'tarantool1:3301', zone = '1' }, { uri = 'tarantool2:3301', zone = '2' }, { uri = 'tarantool3:3301', zone = '3' }, }, login = 'test_user', password = 'pass', redundancy = 1, binary = 3301, } |
[/codesyntax]
Данную конфигурацию можно добавить как в файл инициации БД, так и уже в работающей Базе из консоли:
docker exec -it 71b8935d0cd3 console
… вводим всё вышенаписанное, затем
shard = require('shard')
shard.init(cfg)
И для проверки внесем данные в один из экземпляров tarantool
shard.tester:insert{1,'Tuple #1'}
В другом экземпляре из консоли выполним селект:
shard.tester:select{1}
--- вывод
- - - [1, 'Tuple #1']
Значит репликация работает
Настройка master-slave-slave:
cat docker-compose-replica.yml
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
version: '3.7' configs: app_lua: external: true app_replica_lua: external: true networks: - tnt_cluster services: admin: restart: always image: "quay.io/basis-company/tarantool-admin" ports: - "8000:80" volumes: # - ./tarantool-admin/php:/var/www/html/php # - ./tarantool-admin/public/admin/js:/var/www/html/admin/js # - ./tarantool-admin/public/admin/index.php:/var/www/html/admin/index.php # - ./tarantool-admin/public/admin/style.css:/var/www/html/admin/style.css # - tarantool_admin:/var/tmp - tarantool_admin:/var/www/html/ #- tarantool_admin/public/admin/js:/var/www/html/admin/js #- tarantool_admin/public/admin/index.php:/var/www/html/admin/index.php #- tarantool_admin/public/admin/style.css:/var/www/html/admin/style.css networks: - tnt_cluster - proxy deploy: replicas: 1 # placement: # constraints: [node.hostname == master1] labels: - com.df.notify=true - com.df.serviceDomain=tarantool.swarm.test.ru - com.df.port=80 tarantool1: image: tarantool/tarantool:1.9.2 ports: - "3301:3301" networks: - tnt_cluster configs: - source: app_lua target: /opt/tarantool/app.lua command: [ "tarantool" , "/opt/tarantool/app.lua"] environment: TARANTOOL_MEMTX_MEMORY: 2147483648 TARANTOOL_USER_NAME: master TARANTOOL_USER_PASSWORD: vXDy1C0j volumes: - tarantool1_cfg:/etc/tarantool/ - tarantool1_data:/var/lib/tarantool deploy: replicas: 1 resources: limits: cpus: '0.50' memory: 3G tarantool2: image: tarantool/tarantool:1.9.2 ports: - "3302:3301" networks: - tnt_cluster configs: - source: app_replica_lua target: /opt/tarantool/app.lua command: [ "tarantool" , "/opt/tarantool/app.lua"] environment: TARANTOOL_REPLICATION_SOURCE: replicator:C7H92Foe@tarantool1:3301 TARANTOOL_MEMTX_MEMORY: 268435456 TARANTOOL_USER_NAME: master TARANTOOL_USER_PASSWORD: vXDy1C0j volumes: - tarantool2_cfg:/etc/tarantool/ - tarantool2_data:/var/lib/tarantool deploy: replicas: 1 resources: limits: cpus: '0.50' memory: 3G tarantool3: image: tarantool/tarantool:1.9.2 ports: - "3303:3301" networks: - tnt_cluster configs: - source: app_replica_lua target: /opt/tarantool/app.lua command: [ "tarantool" , "/opt/tarantool/app.lua"] environment: TARANTOOL_REPLICATION_SOURCE: replicator:C7H92Foe@tarantool1:3301 TARANTOOL_MEMTX_MEMORY: 268435456 TARANTOOL_USER_NAME: master TARANTOOL_USER_PASSWORD: vXDy1C0j volumes: - tarantool3_cfg:/etc/tarantool/ - tarantool3_data:/var/lib/tarantool deploy: replicas: 1 resources: limits: cpus: '0.50' memory: 3G networks: tnt_cluster: proxy: external: true volumes: tarantool1_cfg: driver: "rexray/rbd:latest" driver_opts: size: 1 tarantool1_data: driver: "rexray/rbd:latest" driver_opts: size: 3 tarantool2_cfg: driver: "rexray/rbd:latest" driver_opts: size: 1 tarantool2_data: driver: "rexray/rbd:latest" driver_opts: size: 3 tarantool3_cfg: driver: "rexray/rbd:latest" driver_opts: size: 1 tarantool3_data: driver: "rexray/rbd:latest" driver_opts: size: 3 tarantool_admin: driver: "rexray/rbd:latest" driver_opts: size: 1 |
[/codesyntax]
cat app.lua
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
box.cfg { log_level = tonumber(os.getenv("TARANTOOL_LOG_LEVEL")); replicaset_uuid = os.getenv("TARANTOOL_REPLICASET_UUID"); instance_uuid = os.getenv("TARANTOOL_INSTANCE_UUID"); memtx_max_tuple_size = 1048576 + 200; force_recovery = true; checkpoint_interval = 30; checkpoint_count = 3; read_only = false; } local log = require("log") log.info("Info version %s", box.info.version) log.info("box.info.id %s", box.info.id) box.once( "schema", function() box.schema.user.create('replicator', {password = 'C7H92Foe'}) box.schema.user.grant('replicator', 'replication') box.schema.space.create("test") box.space.test:create_index("primary", {unique = true, parts = {1, "integer"}}) end ) local testspace = box.space.test |
[/codesyntax]
cat app-replica.lua
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
box.cfg { log_level = tonumber(os.getenv("TARANTOOL_LOG_LEVEL")); replicaset_uuid = os.getenv("TARANTOOL_REPLICASET_UUID"); instance_uuid = os.getenv("TARANTOOL_INSTANCE_UUID"); memtx_max_tuple_size = 1048576 + 200; force_recovery = true; checkpoint_interval = 30; checkpoint_count = 3; read_only = true; replication = {'master:vXDy1C0j@tarantool1:3301'}; } local log = require("log") log.info("Info version %s", box.info.version) log.info("box.info.id %s", box.info.id) box.once( "schema", function() box.schema.space.create("test") box.space.test:create_index("primary", {unique = true, parts = {1, "integer"}}) end ) local testspace = box.space.test |
[/codesyntax]
Основное отличие двух конфигов это в том что для мастера - read_only = false, для слейвов - read_only = true.
Так же в docker-compose.yml для реплик указывается один и тот репликационный ресурс: TARANTOOL_REPLICATION_SOURCE: replicator:password@tarantool1:3301
Для мастера он отсутствует.
админка доступна на гите:
git clone https://github.com/basis-company/tarantool-admin.git
docker config create app_lua app.lua
docker config create app_replica_lua app-replica.lua
запускаем стек:
docker stack deploy -c docker-compose-replica.yml tarantool
Настройка мастер-мастер на хостовых системах
Важно! Экземпляры тарантула нужно запускать в определенной последовательности:
- Запускаем экземпляр тарантула на 1-вом сервере, в качестве поля listener указываем самого себя.
cat /etc/tarantool/instances.available/my_app.lua
1 2 3 4 5 6 7 8 |
---- <i>box.cfg{</i> <i>listen = '10.230.165.66:3301',</i> <i>replication = {'replicator:пароль@10.230.165.66:3301'</i><i>}</i><i>, -- URI мастера 1</i> <i> </i><i> read_only = false,</i> <i> }</i> <i>--dofile("/usr/share/tarantool/my_app/my_app.lua")</i> ---- |
systemctl start tarantool@my_app
- Далее запускаем экземпляр тарантула на 2-ом сервере, в качестве поля listener указываем самого себя и 1-ый сервер
cat /etc/tarantool/instances.available/my_app.lua
1 2 3 4 5 6 7 8 9 |
---- <i>box.cfg{</i> <i>listen = '10.230.165.67:3301',</i> <i>replication = {'replicator:пароль@10.230.165.66:3301', -- URI мастера 1</i> <i> 'replicator:пароль@10.230.165.67:3301'}, -- URI мастера 2</i> <i> read_only = false,</i> <i> }</i> <i>-- dofile("/usr/share/tarantool/my_app/my_app.lua")</i> ---- |
systemctl start tarantool@my_app
- Возвращаемся на первый сервер и добавляем в поле listener 2-ой сервер
cat /etc/tarantool/instances.available/my_app.lua
1 2 3 4 5 6 7 8 9 10 11 |
---- <i>box.cfg{</i> <i>listen = '10.230.165.66:3301',</i> <i>replication = {'replicator:V6auD6WAizBvITf@10.230.165.66:3301', -- URI мастера 1</i> <i> 'replicator:V6auD6WAizBvITf@10.230.165.67:3301'}, -- URI мастера 2</i> <i> read_only = false,</i> <i> }</i> <i>--dofile("/usr/share/tarantool/my_app/my_app.lua")</i> ---- |
Рестартуем сервис.
Проверяем что в логах нет ошибок и пробуем поочередно подключиться к экземплярам сервиса, пробуем создать спейсы и записать данные с одного и с другого экземпляра, проверяем что они появляются на обоих.
Подключиться к экземпляру этого же сервера можно командой:
tarantoolctl enter my_app ### здесь мы без проблем попадаем в экземпляр без логина и пароля (вроде как подключаемся под учеткой admin)
Подключиться к экземпляру 2го сервера с 1го (или другого сервера) сервера можно так:
tarantool
tarantool> console = require('console')
tarantool> console.connect('replicator:password@10.242.144.4:3301')
Здесь при подключении мы явно указываем логин и пароль для подключения. Необходимо, чтобы у пользователя были необходимые права.
#выдать права на подключение, чтение, запись, выполнение #box.schema.user.grant('replicator', 'read,write,execute,session,usage', 'universe')
Проверить существует ли пользователь командой:
box.schema.user.exists('replicator') ##вернет true или false
box.space # посмотреть все спейсы
Важно!! В консоле тарантула сохраняется история всех команд, в том числе и команды с паролями, поэтому есть необходимость ее зачищать после настроек. Можно это делать так:
os.execute("clear") # очистка истории консоли таранул
---
for i = 1, 255 do
print()
End
-----
либо так, забиваем консоль пустыми строками и для другого пользователя она будет выглядеть пустой
Для настройки шардирования тарантула нам необходимо поставить дополнительный пакет
yum install install tarantool-shard
Необходимо разрушить репликацию и приступить к настройке шардинга.