title: Конспект материала 33 — jepsen.io (Distributed Systems Safety Research, Kyle Kingsbury) source: https://jepsen.io/ (+ классика aphyr.com — оригинальные посты 2013–2015) author: Kyle Kingsbury (aphyr), Jepsen LLC конспект: подготовлено 2026-09-18, TASK-45.37; прочитаны главная страница, индекс анализов (60+ систем, 2013–2026), справочник консистентности jepsen.io/consistency (модели / феномены / зависимости) и 15 анализов полностью: классика aphyr.com 2013–2015 (Redis, Kafka, Cassandra, ZooKeeper, RabbitMQ, Elasticsearch, MariaDB Galera, «Strong consistency models») + современные jepsen.io (etcd 3.4.3, PostgreSQL 12.3, MongoDB 4.2.6, MySQL 8.0.34, Redis-Raft, Redpanda, NATS JetStream, TigerBeetle) статус: P3-источник «после секций», но единственный, где консистентность KB §7 показана «от противного» — на реальных поломках знаменитых БД. Не читать подряд: достаточно таблицы кейсов (§4) + трёх фактов (§6), 20–30 минут. База знаний по консистентности (DDIA гл. 7–9, Alex Xu гл. 6) уже законспектирована — Jepsen даёт к ней живые иллюстрации и числа.
Материал 33: jepsen.io — проверка консистентности реальных БД «сломом»
Jepsen — многолетняя (с 2013) исследовательская программа Kyle Kingsbury (aphyr): реальные кластеры знаменитых БД, очередей и координационных сервисов нагружают, ломают (партиции, крэши, сдвиг часов) и сверяют фактическую консистентность с той, что заявлена в документации. C 2013 года проанализировано 60+ систем; почти в каждом анализе найдены «replica divergence, data loss, stale reads, read skew, lock conflicts». Ценность для нашей секции не в самой теории (вся она уже в KB §5–§7 и DDIA-конспектах), а в числах и формулировках реальных багов, которые превращают абстрактные «аномалии» в конкретные аргументы: «асинхронная репликация + failover — это окно потери подтверждённых записей» перестаёт быть теоретизированием, когда рядом стоят «Redis потерял 56% ack-записей» или «NATS писал на диск раз в 2 минуты».
1. Как устроен Jepsen-тест (методика)
Jepsen — это и открытая библиотека, и серия бесплатных детальных анализов (плюс платные анализы/тренинги по этическому кодексу: кто финансирует — всегда раскрыто, вендор обычно отвечает companion-постом).
| Элемент | Что это | Для интервью |
|---|---|---|
| Кластер | Обычно 5 реальных нод (LXC/EC2), не «локальный тренажёр» | «проверяли на реальном кластере из 5 нод» звучит весомо |
| Нагрузка | Регистры, наборы, bank (переводы, баланс не уходит в минус), list-append, counters, транзакции | банковский тест — классика SD |
| Nemesis | Инъекция отказов: сетевые партиции (random-halves, partition-majority), паузы процесса (GC-stop), крэши, clock skew, membership changes | тот же словарь, что и в хаос-инженерии: partition, pause, crash, skew |
| Чекеры | Knossos — линейзуемость (алгоритм семейства WGL/Lowe); Elle (с 2020, совместно с Peter Alvaro) — транзакции до strict serializability за линейное время с локализованными контрпримерами | «linearizability checker / transactional checker» — словарный минимум |
| Метод проверки | истории операций + зависимостей (write-write, write-read, read-write, realtime) → поиск циклов в графе | цикл в графе зависимостей = нарушение сериализуемости |
| Максима | «Jepsen доказывает наличие багов, но не их отсутствие» (experimental approach to safety verification) | честная оговорка, если спросят про пределы тестирования |
2. Карта консистентности (справочник jepsen.io/consistency)
Справочник — годный одностраничник для ответа «а какая консистентность, собственно, бывает» и для ссылки на модель выше/ниже по силе.
- Две семьи моделей (multi-object транзакции и single-object операции), которые объединяет вершина — strict serializable (serializable + linearizable одновременно).
- Multi-object: strict serializable → serializable → repeatable read / snapshot isolation → monotonic atomic view → cursor stability → read committed → read uncommitted.
- Single-object: strict serializable → linearizable → sequential → causal → writes-follow-reads и PRAM → monotonic reads / monotonic writes / read-your-writes.
- Связь с доступностью (прямо на картинке): всё от cursor stability / snapshot isolation / sequential и сильнее не может быть полностью доступно в асинхронной сети; от read-your-writes и сильнее — максимум sticky-available; слабее — допускает полную доступность. Это готовая формулировка к разговору про CAP/PACELC (KB §7): «строгая консистентность = платим доступностью/латентностью, потому и существуют каскады ослаблений».
3. Типы аномалий (справочник jepsen.io/consistency/phenomena)
«Феномен — это то, что БД делает, а кто-то, где-то посчитал плохой идеей; легальность зависит от модели» (например, G1a легален под Read Uncommitted и нелегален под Read Committed).
| Феномен | a.k.a. | Смысл | Запрещает |
|---|---|---|---|
| G0 | Write cycle | цикл записи | даже RU |
| G1a | Aborted Read | прочитали запись откатившейся транзакции | RU, RC |
| G1b | Intermediate Read | прочитали промежуточное состояние | RU, RC |
| G1c | Cyclic Information Flow | циклический поток информации между транзакциями | RU, RC |
| G-single | Single Anti-dependency Cycle | «если бы я знал твоё значение…» по одному объекту | RR / SI |
| G2-item / G2 | Anti-dependency Cycle | ссора на чтение-запись; G2-item — «предтеча» полного G2 | serializable |
| P0 | Dirty Write | запись поверх незакоммиченного | RU+, все уровни SQL |
| P1 (A1) | Dirty Read | чтение незакоммиченного | RC+ |
| P2 (A2) | Fuzzy/Non-Repeatable Read | чтение, потом чужое изменение, потом повторное чтение с другим результатом | RR+ |
| P3 (A3) | Phantom | предикат нестабилен: между двумя чтениями по WHERE добавилась строка | serializable |
| P4 | Lost Update | потерянное обновление | RR/SI (частично) |
| A5A / A5B | Read Skew / Write Skew | перекосы чтения и записи — именно write skew остаётся под snapshot isolation | serializable |
| Temporal | Long Fork | две версии истории, долго не схлопываются | causal+ |
| Stale Read / Lost Write | — | устаревшее чтение / потерянная запись | linearizable |
Практический вывод для KB §7: write skew (A5B) — аномалия, которую snapshot isolation принципиально не закрывает (оттуда SSI в Postgres), а stale read / lost write — база для разговора об асинхронной репликации и failover.
4. Известные кейсы (выжимки с числами)
| Система | Год | Заявленное | Найдено Jepsen | Ключевое число |
|---|---|---|---|---|
| Redis + Sentinel | 2013 | «CP, консистентность» | при партиции — split-brain (два мастера), старый мастер продолжал ack'ить; при лечении — потеря подтверждённых записей | 56% (1126 из 1998) подтверждённых записей потеряно |
| Kafka (replication) | 2013 | «f−1 узлов терпим» | ISR может схлопнуться до лидера; при потере им ZK-лида — new лидер с пустым логом; потеря ack-записей | потеря произвольных ack-записей |
| Cassandra | 2013 | консистентность настраивается | LWW (последняя запись побеждает) без векторных часов; даже с QUORUM + идеальными часами + идеальным локером | 28% (285 из 1009) подтверждённых записей потеряно; счётчики уплывают до 50% |
| Riak (упомянут в Cassandra) | 2013 | — | чистый LWW без порядка | дроп 30–70% записей даже на R=W=ALL |
| ZooKeeper | 2013 | linearizable | записи линейзуемы (кворум + fsync перед ack); но sync+read — не линейзуем (дополнение 2019) | «география» CP-координатор |
| etcd 0.4 → 3.4.3 | 2014, 2020 | coordination-примитив | 0.4: stale reads по умолчанию; 3.4.3: KV-операции строго сериализуемы, но локи фундаментально небезопасны (два процесса держат лок одновременно, даже в здоровом кластере) | «locks aren’t real»; решение — fencing tokens |
| RabbitMQ | 2014 | очередь | queue-мьютекс на отрицательном ack ломается: невозможно отличить упавший процесс от «задумавшегося» — лок выдают второму владельцу; докум. сама предупреждает «партиции инвалидируют гарантии» | лок держат два процесса |
| Elasticsearch | 2014 | — | при разделении кластера устаревшие копии шарды, исключённые из кластера, продолжали принимать записи; при воссоединении старые документы затирали свежие | расхождение и перезапись данных |
| MariaDB Galera | 2015 | snapshot isolation | транзакции видят промежуточно закоммиченное состояние; заявленный SI «не совсем корректен» | частично закоммиченные чтения |
| PostgreSQL 12.3 | 2020 | serializable / RR | «serializable» нарушал G2-item при нормальной работе (баг конфликт-детекции, патч в 13.08); RR = snapshot isolation (аномалия G2-item легальна там); RC чист | повторяющиеся нарушения G2-item |
| MongoDB 4.2.6 | 2020 | «среди сильнейших гарантий… полные ACID» | даже на максимуме read/write concern не держит snapshot isolation; read skew, G1c, дубли записей, internal consistency; слабые дефолты снимают уровень безопасности тихо | даунгрейд гарантий «молча» |
| MySQL 8.0.34 | 2023 | RR | RR нарушает формальный RR: G2-item, G-single, lost update, internal consistency, monotonic atomic view (видишь часть эффектов транзакции, потом пропадает остальное); RDS MySQL-кластеры нарушают сериализуемость рутинно | «RR несколько сильнее RC, но слабее формального RR» |
| Redis-Raft | 2020 | «эффективно CP» (Raft) | 21 баг в dev-сборках: бесконечные циклы на любой записи, полная потеря данных при любом failover, stale reads, split-brain, aborted reads; в последующих сборках всё кроме одного закрыто | полная потеря на failover |
| Redpanda | 2022 | Kafka-совместимость | 3 liveness + 7 safety: крэши, aborted reads, несогласованные offset'ы, circular information flow, lost/stale messages | 10 проблем, 7 закрыто |
| NATS JetStream | 2025 | at-least-once | потеря коммитов при повреждении файлов на меньшинстве нод; fsync раз в 2 минуты вместо fsync перед ack → потеря подтверждённых записей и стойкий split-brain при отключении питания | ack-записи теряются при питании |
| TigerBeetle | 2025 | Strong Serializability | контрпример: strong serializability выдержана (0.16.30) — ни одной safety-аномалии на партициях; найдены лишь 7 крэшей, бесконечные ретраи по дизайну, «отсутствие» обработки полной потери ноды | «сильные гарантии возможны» |
4.1 Redis + Sentinel (2013) — эталон «асинхронная репликация + failover = потеря»
Самая цитируемая цифра Jepsen. Redis на одной ноде — линейзуемое CP-хранилище; Sentinel добавляет failover: Sentineli (внешний процесс) детектят отказ и назначают нового мастера. Jepsen партиционировал кластер: старый мастер остался в меньшинстве и продолжал принимать и подтверждать записи (асинхронная репликация не требует кворума на запись), Sentineli в большинстве выбрали нового мастера. При заживлении сети старый мастер демотируется (это исправили лишь в 2.6.13 — до этого оба мастера жили вечно), и накопленные им ack-записи молча выбрасываются: 1998 ack из 2000, выжило 872, потеряно 1126 = 56%. Плюс все клиенты — часть распределённой системы: «когда корректность зависит от того, с каким узлом клиент говорит в конкретный момент, клиенты упираются в распределённый консенсус — это чертовски сложно делать правильно».
Вывод под слоты (стыковка с KB §5/§7): у асинхронной primary→secondary репликации принципиально есть окно между подтверждением записи клиенту и её долговечным копированием; failover внутри этого окна теряет данные. «Синхронная» репликация/кворум на запись (W+R>N, ISR-ack) — то, что сужает окно; но кворумы не дают линейзуемости без read repair по правилам (см. Kleppmann, материал 32, и KB §7).
4.2 Kafka (2013) — «терпим f−1 отказов» ≠ CP
Kafka 0.8 заявил репликацию, терпящую f−1 отказов (сильнее классического n/2−1), потому что «majority-кворумы в LinkedIn ненадёжны». Механика: лидер шарда держит ISR (in-sync replicas); запись ack-ится, когда её подтвердил весь ISR. ISR может схлопнуться до одного лидера — тогда лидер ack'ит записи, персистентные только локально; если лидер теряет ZK-клейм, выбирается новый лидер, который может быть сколь угодно позади, — и «новый лидер + старый лидер» дают расходящиеся лог-истории; вариант «сохранить оба» нарушает линейный порядок, вариант «сбросить один» уничтожает подтверждённые данные. Достаточно двух согласованных отказов: «лидер изолирован → крэш/перезагрузка».
Вывод: «f−1 отказов» — это терпимость к отказу членов, а не потеря каузальности между лидерами; единственный способ не терять ack-данные — требовать ack от кворума реплик перед подтверждением (то, что Kafka позже сделал min.insync.replicas / acks=all).
4.3 Cassandra (2013) — LWW без векторных часов
Dynamo-стиль (кольцо, N реплик, hinted handoff, антиэнтропия), но вместо векторных часов — last-write-wins (ради 2 round-trips → 1). Jepsen: даже «идеальные» условия — синхронизированные часы, ConsistencyLevel.QUORUM/ALL, внешний идеальный локер, последовательные записи в одну ячейку — дают 28% потери подтверждённых записей (285 из 1009). LWW без строгого внешнего порядка не гарантирует ничего: «единственное условие, при котором запись не будет молча проигнорирована — неизменяемое значение». Векторные часы/CRDT устраняют потери (G-set в Riak — 100% выжили; CQL-append в Cassandra — те же 100%). Счётчики Cassandra — не PN-счётчик: при партиционировании уплывают до 50%.
Вывод: AP-системы требуют thinking в терминах order-free структур (CRDT/коммутативных слияний) — это готовый аргумент в блоке «почему AP и чем платим» (Dynamo, материал 28; KB §5/§7).
4.4 ZooKeeper и etcd (2013/2014/2020) — хорошо там, где узко, и ловушка локов
ZK: linearizable записи (кворум + fsync перед ack), best of small state. etcd 0.4 (2014): stale reads по умолчанию (любой узел читал локально, не проверяя, актуален ли лидер) — «redis-пойнт»: если реплика читает без quorum-флага, linearizability теряется. etcd 3.4.3 (2020): KV-операции и микротранзакции строго сериализуемы (проверено на партициях, паузах, крэшах, clock skew, membership changes), watches отдают каждое изменение в порядке — а вот локи: «locks aren’t real» — даже в здоровом кластере два процесса могут держать etcd-лок одновременно (плюс баг: не проверялась валидность lease после ожидания). Рекомендация Jepsen: локи для производительности (вероятностное ограничение конкурентности) — можно; для безопасности — нельзя: ресурс должен быть безопасен без лока (fencing tokens, например, revision из etcd).
Вывод: это прямая иллюстрация к KB §7 (fencing-токены, zxid/revision/epoch). Ответ «зачем fencing-токен» = «именно это Jepsen и показал на etcd/ZK: лок держат двое, дешевле сделать ресурс безопасным под повторяющиеся фенсинг-токены».
4.5 PostgreSQL 12.3 (2020) — имена isolation-уровней обманывают
Анализ на транзакционном чекере Elle (работа с UCSC, без оплаты): serializable в 12.3 нарушал G2-item при нормальной работе (баг в конфликт-детекции — параллельные update+insert путали, какая транзакция виновата; патч в августе); repeatable read — на самом деле snapshot isolation (подтверждено Kleppmann/Hermitage: G2-item легален там; сильный snapshot isolation при этом держался); read committed чист (ни G0, ни G1a/G1b). Урок про подход: Postgres-тесты isolationtester и Hermitage проверяли только «вручную доказанные» сценарии; Elle генерирует широкий класс транзакций и ловит то, что никто не додумался проверить — property-based тестирование вместо набора хрестоматийных кейсов.
Вывод: «на чём храните деньги/заказы» — уровень изоляции надо называть по феноменам, которые он реально запрещает, а не по имени ANSI-уровня.
4.6 MongoDB 4.2.6 (2020) — «+ACID» на бумаге
Документация: «среди сильнейших гарантий консистентности… полные ACID-транзакции». Jepsen: даже на максимальных read/write concern нарушается snapshot isolation; наблюдались read skew, G1c (циклический поток), дубли записей, внутренние рассинхроны; слабые дефолты тихо снижали уровень безопасности (транзакции могут терять записи и видеть dirty reads без единой ошибки), а snapshot read concern «включал» snapshot только в паре с write concern=majority — даже для read-only транзакций. May 2020: MongoDB заявила, что нашла баг в механизме ретраев транзакций (патч 4.2.8).
Вывод: «ACID-транзакции» — маркетинг; сильные гарантии требуют явных concern'ов на каждый запрос и проверки тестами (это сюжет и для интервью: «как вы выбираете БД под заказы» — по декларируемым и проверенным гарантиям).
4.7 MySQL 8.0.34 (2023) — повтор 2014-го, теперь с Elle
Повтор Kleppmann's 2014 Hermitage: RR в MySQL позволяет G2-item, G-single и lost update, плюс новые для Elle находки: нарушения internal consistency и monotonic atomic view (транзакция видит часть эффектов другой, потом «забывает» остальные). Вывод: «RR несколько сильнее Read Committed, но слабее формального Repeatable Read» (по Adya/Berenson). Бонус: AWS RDS MySQL-кластеры при репликации нарушают serializability «рутинно».
4.8 Redis-Raft (2020) — 21 баг в Raft-рендезинге Redis
Первый полный Jepsen-анализ, где стеки транзакций проверял новый чекер Elle: в dev-сборках Redis-Raft (1b3fbf6…e0123a9) найдено 21 issue: полная потеря данных при любом failover (новый лидер выходил с пустым состоянием), бесконечные циклы на любой записи при follower-proxy (нет re-entrancy check — команда прогонялась через Raft-лог вечно), stale reads даже в здоровом кластере (лидер не публиковал no-op при вступлении в должность), split-brain с потерей обновлений, спазматические NOLEADER. К концу цикла всё, кроме одного крэша, исправлено. Заодно честная карта репликации Redis: Sentinel «eventually consistent, merge = last failover wins», Cluster «окна потери ack-записей», Enterprise CRDT «LWW для строк — subject to lost updates» — никакой из трёх не гарантирует отсутствие потерь. WAIT не делает систему строго консистентной.
4.9 Современные очереди (Redpanda 2022, NATS 2025) и контрпример TigerBeetle (2025)
- Redpanda (Raft внутри, Kafka-протокол): 3 liveness + 7 safety — крэши, aborted reads, несогласованные offset'ы, circular information flow, lost/stale messages; 7 закрыто к публикации.
- NATS JetStream (2025): at-least-once по документации — а потеря коммитов при повреждении файлов на меньшинстве нод; отключение питания в связке с сетевыми задержками → потеря подтверждённых записей и стойкий split-brain. Причина названа прямо: fsync раз в 2 минуты, а не перед ack. Показательный случай разрыва «ack ≠ durable».
- TigerBeetle (2025): редкий контрпример: strong serializability устояла на всех партициях/крэшах/дисковых повреждениях (вплоть до порчи файлов всех реплик) — при стоимости дизайна (двойная бухгалтерия, LSM, ручной операционный контракт). Найдено «всего» 7 крэшей, бесконечные ретраи по дизайну, отсутствие сценария полной потери ноды.
5. Системные уроки Jepsen (что обобщается поверх кейсов)
- Асинхронная репликация + failover = окно потери подтверждённых записей (Redis 56%, Kafka ISR→1, Mongo слабые дефолты, NATS fsync 2 мин, ES устаревшие шарды). Гарантия клиенту даётся только когда запись долговечна (кворум/ISR/fsync перед ack).
- Документация врёт сильнее, чем код. Почти каждый анализ начинается с цитаты из доков и заканчивается несовпадением: Redis «CP», Kafka «f−1», etcd «sequential — сильнейшая», MongoDB «full ACID», Cassandra «QUORUM = safety».
- Локи в лучшем случае — вероятностное ограничение конкурентности: etcd «locks aren't real», RabbitMQ-мьютекс. Безопасность даёт fencing-токен на защищаемом ресурсе — никогда локи как таковые (KB §7).
- Имена ANSI-уровней ≠ формальные определения: PG RR — это SI; MySQL RR слабее формального RR; PG «serializable» с поломанной конфликт-детекцией. Надо называть феномены.
- fsync — отдельный и последний рубеж: ack раньше fsync = потеря при питании (NATS). Мастер-репликация решает доступность, не долговечность.
- Свойство проверяется только ломкой: ручные сценарии (isolationtester, Hermitage) ловят известное; генеративные чекеры (Elle) находят новое. Отсюда — краеугольный камень для ответа про тестирование распределённых систем.
6. Три факта для интервью (и одна запасная)
- Redis + Sentinel (Jepsen, 2013): 56% подтверждённых записей потеряно при партиции — «при партиции старый мастер продолжал ack'ить в своём меньшинстве, Sentinel выбрал нового, и его записи выбросили; так работает любой failover поверх асинхронной репликации». Подача: в ответ «почему не Redis как БД/итог для ленты» или «как не терять данные» — «ack только после долговечности: кворум или запись в лог с fsync, плюс идемпотентность клиента».
- Postgres 12.3 и MySQL 8.0.34: имена isolation-уровней не равны формальным — «Jepsen показал: PG repeatable read — это snapshot isolation (write skew разрешён), а serializable нарушал G2-item; MySQL RR слабее формального RR». Подача: «на чём храните заказы» — «выбираем уровень по феноменам: serializable/SSI, если важны unique-констрейнты и счётчики; считаем SI недостаточным для денег».
- etcd-lоки небезопасны (Jepsen, 2020) — «KV-операции в etcd строго сериализуемы, но два процесса могут держать лок одновременно; поэтому безопасность строится на fencing-токенах (revision), а не на лочах». Прямо стыкуется с KB §7.
- (запасная, если спросят про очереди/брокеры) NATS JetStream (2025): «ack до fsync (раз в 2 минуты) = потеря подтверждённых сообщений при отключении питания; для очередей долговечность подтверждается только после устойчивой записи».
7. Как пользоваться под слоты
- Режим: не читать подряд; 20–30 минут: таблица §4 + §6 (факты для интервью) + §5 (уроки). Детали 4.1–4.9 — по мере надобности, когда тема всплывёт в бриф.
- Стыковка с базой: KB §7 (консистентность/консенсус — все модели и fencing-токены), KB §5 (репликация: кворумы, read repair), KB §10 (эксплуатация: fsync, долговечность),
articles/09-consistency.md; число латентностей/сроков тут не нужно — Jepsen про гарантии, а не про размеры. - Соседи по теме:
lsd-kleppmann-lectures.md(45.36, кворумы ABD «не линейзуемы», 2PC, полный Raft — теория, которую Jepsen опровергает/подтверждает на практике),lsd-awesome-distributed-systems.md(45.32, Dynamo AP-рамка — «почему AP»),lsd-polomodov-guide.md(45.20, в Q&A стоит «Jepsen-тесты — как проверять заявленные гарантии под нагрузкой/дрифтом часов»). - Аналогия для интервью «как вы тестируете распределёнку»: Jepsen-подход = property-based + отказы (partition/pause/crash/skew) + чекер, ищущий контрпример к заявленной модели; в лайт-версии это же делают Chaos Monkey/chaos engineering. Названный «Elle» или «Knossos» в нужном контексте — признак глубины, но без воды: «проверяем гарантии на слом, а не на сценарии из доков».
8. Прочитанные материалы (что именно легло в конспект)
- jepsen.io:
/(о проекте, методика, новости),/analyses(индекс 60+ систем с датами и версиями),/consistency+/consistency/models,/consistency/phenomena,/consistency/dependencies(справочник моделей/феноменов по Adya, ANSI/Berenson, Viotti & Vukolic). - Анализы (jepsen.io, полные тексты): Redis-Raft 1b3fbf6 (2020), PostgreSQL 12.3 (2020), etcd 3.4.3 (2020), MongoDB 4.2.6 (2020), MySQL 8.0.34 (2023), TigerBeetle 0.16.11–0.16.30 (2025), NATS JetStream 2.12.1 (2025), Redpanda 21.10.1 (2022).
- Классика (aphyr.com): «Call Me Maybe» Redis (283), ZooKeeper (291), Kafka (293), Cassandra (294), Redis redux (307), «Strong consistency models» (313), RabbitMQ (315), etcd & Consul (316), Elasticsearch (317), MariaDB Galera (327), «How to stop data loss»-тема в Redis-redux; страницы частично обрезаются для curl — там, где текст обрывался, использованы цитаты, попавшие в выжимку, и абстракты.
- Примечание: «анализа Redis 2018» на jepsen.io/aphyr нет (в индексе Redis — только 2013/2013-WAIT и Redis-Raft 2020); сюжет «Redis теряет подтверждённые записи» закрыт проверенными фактами 2013 + Redis-Raft 2020 (цитаты доков Sentinel/Cluster/Enterprise).