⭕️ Anonymous Распредчан 24.10.2025 03:25 #70970
4 октября 2025 года было сказано приступить к проектированию распределённого чана.
Эта нить посвящена проблемам, обсуждению их и публикации новостей по данному проекту.
Распредчан - это кодовое название механизма синхронизации данных между держателями нод нашего чана.
Нода - ресурс, предоставляющий интерфейсы для server2server и server2client взаимодействий, где s2s - связь между нодами, а s2c - связь между нодой и интерфейсом, например между pissykaka и pissychan-front.
Какие проблемы мы хотим решить?
Независимое хранение постов без централизации оного в руках полутора анонов.
Распределённое хранение файлов.
Возможность каждой ноды принимать посты и файлы от s2c-коннектов для последующей синхронизации их с другими нодами, в том числе теми, что были оффлайн некоторое время.
Мы открыты к предложениям, обсуждению и критике данного проекта.
⭕️ Anonymous 24.10.2025 12:35 #70985
На данный момент мы заняты разработкой системы прав доступа нод.
Одно из предложений звучит так:
> Касательно прав нод у меня такое виденье.> Ноды могут обладать правами:Чтения досок, постов и файлов с других нод - думаю, всем нам проще и спокойнее будет обмениваться данными только с известными нодами.
⭕️ Anonymous 24.10.2025 12:36 #70986
Блядь, попердолил разметку.
Ну вы понели, где и что.
🔰 kugichka Верхнеуровневое видение списка эвентов. 24.10.2025 18:04 #70992
Есть: доски, треды/посты, файлы, паспорта
Эвенты доски:
создание доски
удаление доски
модификация метаданных доски (tag, имя, скрыто-статус, etc)
Так же следует отметить следующие кейсы:
когда одна из нод содержит исключительно свою доску, эта часть ноды (доска) перестаёт считаться частью сети, эвенты не фиксируются в кафке, а всевозможные коллизии разруливаются хостом ноды
сейчас доски имеют свой id в качестве идентификатора, и будет перекат в использование tag в качестве идентификатора
Эвенты постов:
создание поста
удаление поста (физическое, не модерация)
изменение метаданных поста (текст, медиа, updated_at)
перемещение оп-поста на другую доску
Эвенты файлов:
создание файла
изменение меты файла (при модерации например, чтобы вести на заглушку после удаления)
удаление файла (физическое опять же)
Эвенты паспортов:
создание паспорта
разделегирование паспорта (aka удаление)
Эвенты на будущее:
смена паблик ключа для подписей/идентификации ноды
🔰 kugichka 24.10.2025 18:05 #70993
Чуть попозже продолжу это конкретной схемой для кафки, с подсвечиванием важных нюансов.
🔰 kugichka 25.10.2025 00:20 #71002
⭕️ Anonymous 31.10.2025 04:15 #71198
А может синхронизировать явно выбранные доски, евенты же посылать всегда?
⭕️ Anonymous 02.11.2025 05:54 #71282
А можно да. А что ты подразумеваешь под «явным выбором»?
⭕️ Anonymous 02.11.2025 15:29 #71292
Типа, владельцы нод сами решают, какие посты и на какие доски они будут у себя сохранять. При старте ноды конфигурируешь - "обрабатывать евенты с досок такой-то и такой-то".
Написал я, и что-то призадумался. Модерация распределённой системы это прям жесть какая-то. Наверное, твой вариант лучше - изначально складировать как есть. В конце концов, владельцы-трясуны на своей ноде могут и премодерацию ввести - не показывать посты до тех пор, пока своей волею не разрешат.
Даже не знаю, что и лучше. Во втором варианте консьюмеры выходят чище и проще, что безусловно хорошо.
⭕️ Anonymous 03.11.2025 07:24 #71301
Тоже верно. Слушай, можно и первым, и вторым способами. Они всё равно заключаются в реализуемых механиках самой ноды, т.с. в её конфиге это живёт.
⭕️ Anonymous 04.11.2025 03:40 #71323
Что ж, я полуркал информацию о том, как можно выполнять верификацию подписи автора поста в распределённой модели.
Напоминаю, что я вижу проблему в таком кейсе:
Нода N1 выпустила новый паспорт K1.
Пользователь создал пост с подписью от K1.
N1 отправила евент о посте в кафку.
При попытке отправки евента о новом паспорте N1 упала, и евент не был зафиксирован.
N2 синхронизирует события с N1, в них содержится пост с подписью от K1, но у N2 нет K1 для верификации.
Что делать?????
Нейродаун подсказал мне весьма простое, как сказал бы Хома, решение в своей логичности - ставить на некоторое время такой пост в статус "Ожидает проверки подписи". Однажды список паспортов будет синхронизирован между участниками сети, и верификация пройдёт успешно.
В таком случае и городить цепочки сертификатов, равно как и менять текущую реализацию паспортов не следует. Следует лишь с каждым постом хранить и отправлять в евенте хеш его паспорта.
Сейчас используется алгоритм хеширования SHA256 - https://github.com/U-Me-Chan/umechan/blob/master/chan-api/src/Posts/Post/PasswordHash.php#L47C21-L47C21
ХЗ, мб это покажется недостаточным и можно его усложнить для успокоения в век дешёвых терафлопсов.
⭕️ Anonymous 04.11.2025 03:44 #71324
Ох, я ввёл в заблуждение.
Для паспорта используется SHA512. SHA256 используется для хеша пароля поста.
⭕️ Anonymous 04.11.2025 18:36 #71335
⭕️ Anonymous 04.11.2025 18:36 #71336
/s/сейчас да/сейчас два
⭕️ Anonymous 20.11.2025 19:43 #71770
@kugichka, ты предполагаешь, что события в кафке не удаляются никогда?
🔰 kugichka 21.11.2025 07:58 #71782
Не предполагаю, а щито?
⭕️ Anonymous 21.11.2025 12:14 #71784
А как новые ноды будут синкать старые посты?
⭕️ Anonymous 21.11.2025 12:27 #71785
Это хороший вопрос. Мне тут на работе архитектор микросервисов сказал, что юзать кафку для синхронизации данных ПОВЕРХ уже существующих -- самое то, а вот чтобы с нуля восстановить состояние -- кафку не юзают, типа она ваще не для этого. Из тех же рабочих кейсов: тимлид просто присылает дамп бд стейджа, ну или сам вытягиваешь если доступ есть. Это хуйня решение, но чисто технически самое простое.
Тот же чел посоветовал механизм запилить, типа, условный GET /db/all (с ключом ноды) и оно отдаёт всё что есть на текущий момент. При условии, конечно, что ты не всю базу отдаешь за раз, а по отдельным табличкам, при том с оффсетами-лимитами.
⭕️ Anonymous 21.11.2025 12:30 #71786
Хорошо, тогда вытекающий из этого вопрос - какое время жизни сегмента топика? Месяца точно должно хватить всем тем, кто падал надолго, я думаю.
⭕️ Anonymous 21.11.2025 22:05 #71804
Да, давай договоримся так, «месяца хватит всем», ящитаю.
⭕️ Anonymous 16.12.2025 09:18 #1765862322137210
Мне не нравится IPFS по многим причинам:
Большой транзитный трафик.
Невозможность инкрементальных бекапов штатными средствами.
Трудности с деплоем на публичных хостингах - BitTorrent обычно запрещён правилами.
Нет возможности организовать приватную сеть из коробки.
⭕️ Anonymous 16.12.2025 09:27 #1765862866083682
Вдогонку мне из-за этого не нравятся S3-подобные решения. Либо я что-то недоизучил, поправьте меня, пожалуйста.
⭕️ Anonymous 26.12.2025 04:48 #1766710102977458
Что ж. Лог мыслей.
Я развернул локально Kafka-ноду в режиме KRaft, пописял в тестовый топик сообщениями с помощью консольных скриптов продюсера и консьюмера, входящих в поставку образа apache/kafka с Dockerhub.
Пытался завести kafka-ui - не вышло, находящиеся в одной подсети контейнер кафки и кафка-юайя не видят, штоли, друг друга.
Полюркал насчёт библиотек для работы с Kafka в PHP - есть по сути лишь одна (актуальная), она требует отдельного PECL-модуля.
До этого я бегло ознакомился с помощью подкастов с внутренней кухней Kafka, хочу чуть глубже погрузиться в это - про патрицирование топиков, реплики(и как они нам не помогут), отключение автокоммита, как работать с оффсетом топика при чтении оттуда, права доступа.
Меня смущает schemaless топиков - надо бы узнать, есть ли возможность задавать строго.
Очень много настроек самой кафки, в которых я пока нифига не понимаю.
Настройки производительности - кафка это джява, а джява это жор памяти и процессорного времени. Плюс выявить, что мне нужно будет обложить алертами в Grafana.
⭕️ Anonymous 26.12.2025 05:19 #1766711966605713
...и я не могу его собрать, т.к. он требует в alpine linux librdkafka-dev, который гвоздями прибит к openssl, вместо которого у меня используется libressl-dev для решения проблемы сборки модуля memcached. Уф. Перекатывать образ на бубунту снова?
⭕️ Anonymous 26.12.2025 15:53 #1766750005523988
Сегодня выяснил, что для модуля memcached уже не надо libressl-dev, он собирается и без этого. Крутяк!!
⭕️ Anonymous 30.12.2025 11:53 #1767081231441257
@kugichka, почему мы свои инстансы кафки не можем объединить в единый кластер, например? Ты такую схему и предполагал?
Получается же три пути:
Единый кластер. Каждая нода потребляет и продюссирует в локальный инстанс кафки.
Каждая нода продюссирует сообщения в локальную кафку и потребляет из удалённой кафки.
Перед удалённой кафкой есть какое-то API? Не, бред какой-то же.
Расскажи свой взгляд.
🔰 kugichka 10.01.2026 20:20 #1768062026241065
Ну, вот второй варик и предлагал.
⭕️ Anonymous 13.01.2026 12:21 #1768292495026871
Значит, мне надо хорошенько разобраться с вопросами аутентификации консюмеров. Равно как я всё-таки хотел придумать что-то с реализацией валидации схемы евентов, только без централизованного хранилища. Мб, заводить топик под каждую новую версию евента тут выглядит разумно.
⭕️ Anonymous 24.01.2026 22:22 #1769278946216015
Как узнать, что у двух нод разошлись версии БД? Как впоследствии разрешать такие коллизии? Нода дожна как-то узнать, что у неё нет поста, который есть у другой ноды. А ещё должна как-то его получить.
⭕️ Anonymous 24.01.2026 23:24 #1769282673099122
Эти два дня я боролся с проблемой, присущей PHP. У меня не успевали некоторые события, если их несколько на запрос, складываться в Kafka. При этом, если я делал sleep(2) после выполнения операции отправки очереди сообщений в брокер, до всё доходило! Дрожащими руками полез в Сеть, и нашёл параметр socket.timeout.ms, который(неочевидно из названия) отвечает за время блокировки сокета брокером(?). Это время применяется к операции чтения расширением librdkafka из сокета, а также как часто основной тред расширения будет проверять, является ли сокет terminated. Посоветовавшись с некоторыми материалами Сети, нейродаунов и issues на гитхабе расширения, выяснил, что стандартное время установлено в 1000, а ежели его установить в меньшее по совету источников, то сообщения будут приходить во-вре-мя. Выглядит как рабочее колдунство; смущает.
Полюркал инфу про аутентификацию консумеров, интересует прежде всего SASL/PLAIN, т.к. он не требует многих телодвижений с java keystore и форматами сертификатов. Пока не осилил. Боюсь обосраться в этом моменте, а ведь мне торчать этой полуголой жопой как минимум для одного адреса в Сети.
Что ж, на данный момент я закончил реализацию механизма продюссирования евентов на большинство событий записи в БД чана, попробую теперь реализовать консумера, что будет потреблять сообщения на удаление постов из файлстора при удалении поста овнером чана или автором поста.
⭕️ Anonymous 02.02.2026 11:36 #1770017776401876
Разберём причины появления такого инцидента и пути решения.
Почему могут расходится БД pissykaka и epds?
В pissykaka приходит запрос на создание поста.
Pissykaka кладёт пост в БД, затем пытается отправить евент в брокер.
Брокер упал/не сделали flush/другое.
Теперь пост есть на pissykaka и нет в edps.
Самый глупый способ разрешения:
К chan.kugi.club приходит запрос на получение определённого поста.
Поста нет в epds.
chan.kugi.club отдаёт 404 с надписью "возможно, такого поста не было никогда либо он ещё не синхронизирован".
epds делает запрос к pissykaka по HTTP и вытягивает данные поста.
Сетевое взаимодействие, отсутствие гарантии доставки евента, неоднородные сообщения состояния.
Способ второй:
Каждый пост обладает статусом, который принимает такие значения: "Локальный", "Синхронизирован", "В процессе".
Если мы сохранили пост в БД, то затем некий сервис получает такие посты и отправляет евенты брокеру, обновляя затем статус поста. Получаем что-то вроде Outbox курильщика.
Много операций записи, отдельный сервис-продюсер.
Способ два с половиной, оутбокс с очередью.
Принимаем запрос, складываем его в in-memory очередь навроде memcached, redis, etc.
Сервис затем складывает их в БД и кафку.
Отдельный сервис, отсутствие гарантии сохранности поста при падении сервиса очереди.
Способ третий:
При обработке запроса на запись данных поста мы гарантируем, что отдадим 201 тогда и только тогда, когда пост будет сохранён в БД и будет отправлен евент в кафку. Если кафка упала - откатываем транзакцию в БД.
Много синхронных операций при отправке поста. Здесь мы гарантируем, что пост существует только тогда, когда он есть и в БД, и в кафке. Типа как в банках. Здесь надо нагрузочных тестов, гарантирующих обработку запроса не позже 500 мс, например.
Почему расходятся epds и pissykaka, version 2:
epds и chan.kugi.club с пару месяцев являются лидером.
pissykaka подняли
Надо как-то синхронизироваться, в кафка евенты уже протухли.
pissychan как-то должен узнать, кто лидер. (epds и pissykaka должны как-то решать, кто из них лидер и когда. Балансер? Роунд-робин? А мы федерацию делаем или мастер-слейв?)
epds и pissykaka должны иметь идентичный REST API для c2s-коннектов с pissychan и другими.
Бекендер вернётся с другими неприятными мыслями через некоторое время.
⭕️ Anonymous 03.02.2026 03:58 #1770076703417562
Оффсет сохраняется для конкретной партиции топика и consumer group_id! Ранее я считал, что оффсет привязан лишь к партиции - это не так. Следовательно, два потребителя могут читать из одного топика и одной партиции независимо сообщения, сохраняя оффсет в кафку manual путём, т.е., без автокоммита.
Я боялся, что в случае разрастания сети придётся либо отправлять сообщения в разные топики/партиции, увеличивая количество I/O операций на процесс обработки запроса создания поста, либо строить сеть по принципу тунеллирования - новая нода синхронизируется epds, тот синхронизируется с pissykaka для равномерного распределения подключений.
Но полученная инфа всё меняет. Я могу спокойно при обработке запроса использовать механизм распределённой транзакции:
Открыть транзакцию в СУБД.
Записать туда данные поста.
Отправить сообщение в Kafka.
Если при отправке в Kafka произошла ошибка - выполнить rollback у СУБД, отдать неуспешный ответ клиенту. Возможно, положить обработку сообщения в отдельный топик "на потом".
Если всё успешно - закрыть транзакцию в СУБД, отдать успешный ответ клиенту.
Совершенно необязательно. @Oxore может просто решить зависить всегда от стабильности pissykaka, как сейчас, и не имплементировать интерфейс к epds.
Ноды одноранговые. Не вижу смысла мутить тут выбор некоего лидера, переключать клиенты на него и прочая.
⭕️ Anonymous 11.02.2026 04:12 #1770768777726367
С грехом пополам и с помощью alice.yandex.ru я смог настроить механизм SASL/PLAIN для порта Kafka, который у меня будет принимать коннекты от внешних консумеров. SASL/SSL не хочу, надо будет либо выпускать самоподписанные сертификаты, либо готовить PEM-сертификат из моего публичного. Как решение, попробую проксировать соединение к Kafka с помощью Nginx в режиме stream proxy.
Починенные евенты скоро.