ЗАМЕР
bench/valkey-cluster/runs/discovery.txt
Скрипт, которым получены числа в статье, и запись прогона. Файл читается на сборке из репозитория — это тот самый код, который запускали, а не его копия.
- Цитируется в статье
- /ru/system-design/caching/valkey-clustering
Запись прогона
У этого замера записи прогона нет — только скрипт.
Скрипт
118 строкValkey 9.1.2 · один хост, процессы на случайных портах
нативный кластер (6 узлов) и связка Sentinel (1 мастер + 2 реплики + 3 sentinel)
1. КЛАСТЕР ОТВЕЧАЕТ НЕ ДАННЫМИ, А АДРЕСОМ
----------------------------------------------------------------------
CLUSTER KEYSLOT foo 12182
узел 44997 (мастер): SET foo 1 MOVED 12182 127.0.0.1:48711
узел 53953 (мастер): SET foo 1 MOVED 12182 127.0.0.1:48711
узел 48711 (мастер): SET foo 1 OK
узел 39529 (реплика): SET foo 1 MOVED 12182 127.0.0.1:48711
узел 54583 (реплика): SET foo 1 MOVED 12182 127.0.0.1:48711
узел 51665 (реплика): SET foo 1 MOVED 12182 127.0.0.1:48711
Пять узлов из шести ответили одинаково и не данными. MOVED — это не
ошибка в обычном смысле: узел не отказал, а сказал, КУДА идти, и
назвал слот. Клиент кластера на таком ответе чинит свою карту слотов
и повторяет команду по названному адресу; «глупый» клиент, как
здесь, просто видит текст.
Адресация тут вообще не про узлы, а про слоты: ключ отображается в
один из 16 384 слотов, а уже слот принадлежит узлу. Поэтому
переезд данных между узлами не меняет ни одного ключа — меняет
владельца слота.
2. В РЕЖИМЕ SENTINEL УЗЕЛ ДАННЫХ ПРО ТОПОЛОГИЮ НЕ ЗНАЕТ НИЧЕГО
----------------------------------------------------------------------
узел данных 43471: CLUSTER INFO ERR This instance has cluster support disabled
узел данных 43471: роль master
узел данных 50535: роль slave
sentinel 50997: SENTINEL get-master-addr-by-name 127.0.0.1:43471
sentinel 50997: сколько реплик знает 2
sentinel 50997: сколько других sentinel знает 2
sentinel 50997: CONFIG RESETSTAT ERR unknown command 'config', with args beginning with: 'resetstat'
Первая строка — весь ответ на вопрос «а нельзя ли спросить у самого
узла». Нельзя: узел данных вне кластера про кластер не знает и
честно об этом говорит. Он не знает и того, что за ним кто-то
наблюдает: роль он покажет свою (master или slave), а вот кто
мастер С ТОЧКИ ЗРЕНИЯ СИСТЕМЫ — вопрос не к нему.
Отвечает на него отдельная служба, и она не хранит данных. Последняя
строка показывает, насколько отдельная: у sentinel даже нет команды
CONFIG. Это не урезанный узел, это другой набор команд на том же
двоичном файле.
3. ЧТО ДЕЛАЕТ НАСТОЯЩИЙ КЛИЕНТ КЛАСТЕРА ЗА ОДНУ КОМАНДУ
----------------------------------------------------------------------
клиенту дан один адрес из шести 127.0.0.1:51665
окно наблюдения 2 с, и столько же вхолостую для контроля
узел вхолостую с клиентом что пришло за второе окно
44997 4 8 client|setinfo×2 command×1 hello×1 replconf×2
53953 4 4 replconf×2
48711 4 8 client|setinfo×2 hello×1 replconf×2 set×1
39529 2 2
54583 2 2
51665 (адрес клиенту) 2 7 client|setinfo×2 cluster|slots×1 hello×1 set×1
Считают сами узлы: это их счётчик обработанных команд. Контрольное
окно вхолостую нужно потому, что узлы кластера всё время говорят друг
с другом по шине; клиентское видно только на его фоне.
Видно, что клиент сделал на самом деле: сходил к единственному
известному адресу за картой слотов (cluster|slots) и уже по карте
отправил запись туда, куда надо (set). Команды hello и
client|setinfo — это клиент представляется; они к поиску узла
отношения не имеют.
Два лишних на первый взгляд следа стоит прочитать правильно. Пара
replconf — это разговор мастера с его репликой, он идёт и без
клиента. А select с set на ЕЩЁ ОДНОМ узле — это та же самая запись,
доехавшая до реплики по репликации: клиент к этому узлу не
подключался вовсе. Команды в счётчике узла — не обязательно команды
от клиента, и здесь это видно прямо.
Отсюда свойство, которое обычно и имеют в виду под «кластер сам
разбирается»: знать все узлы клиенту не нужно, достаточно одного
живого. Карту он получит от него и дальше будет ходить напрямую —
посредника между клиентом и данными в этом режиме нет вообще.
4. ЧТО ДЕЛАЕТ НАСТОЯЩИЙ КЛИЕНТ SENTINEL ЗА ОДНУ КОМАНДУ
----------------------------------------------------------------------
клиенту дан один sentinel и имя набора 127.0.0.1:50997 / cache
окно наблюдения 2 с, и столько же вхолостую для контроля
узел вхолостую с клиентом что пришло за второе окно
мастер 43471 14 22 client|setinfo×2 hello×1 ping×6 publish×3 replconf×4 set×1
реплика 50535 14 19 ping×7 publish×6 set×1
реплика 51415 14 19 ping×7 publish×6 set×1
sentinel 50997 (адрес клиенту) 8 11
sentinel 37267 8 8
sentinel 44483 7 8
Порядок обратный третьему блоку: сначала вопрос СЛУЖБЕ, потом
команда данным. Узел данных не участвовал в поиске самого себя и не
мог бы: у него для этого нет ни команды, ни сведений.
Фон здесь заметнее, чем в кластере, и в нём же видно устройство
службы. Sentinel непрерывно опрашивает данные (ping) — отсюда
колонка «вхолостую». А publish на узлах ДАННЫХ — это как раз то, чем
sentinel находит других sentinel: они публикуют себя в канал самого
узла и там же друг друга слышат. Отдельного реестра у них нет;
общая точка встречи — наблюдаемый узел.
Имён команд у sentinel нет ни в одной колонке по той же причине, что
и CONFIG в блоке 2: у него нет commandstats, только общий счётчик.
Практическое следствие, которое из этого растёт: в режиме Sentinel
клиент обязан ходить через библиотеку, умеющую sentinel, и держать
адреса sentinel в конфиге. Если он подключится прямо к адресу
данных — он будет работать ровно до первого переключения, а потом
молча начнёт писать не туда. Что именно при этом происходит, видно
в блоке про возвращение старого мастера.