LINUX.ORG.RU

Форум на NoSQL (key=value).

 


0

2

На правах мыслительных экспериментов, никаких задач не стоит, никакие проблемы не решаются (типа «заборем mysql по скорости!»). Наоборот куча новых проблем с консистентностью. Все ставящиеся тут проблемы вымышлены, безумны и не нужны.

Придумаем как можно держать модели данных, нужные для форума, в какой-нибудь NoSQL. Придумаем какие типы данных в NoSQL были бы полезны ещё, кроме key=value.

Желательно рассматривать nosql субд, которая внутри имеет B+-Tree, т.е. умеет упорядочивать ключи, а не просто держит их в огромной hashtable. Или какой-нибудь LSM типа LevelDB - неважно.

Считаем, что транзакций у нас нет, жизнь боль. Бизнес-логика должна так манипулировать БД, чтобы оставлять её в консистентном состоянии, максимум оставляя мусор в ней. Допустим у нас есть некий уборщик мусора в бизнес-логике приложения, который умеет иногда лениво походить по базе и подропать потерявшиеся ключи или что-то ещё, т.е. знает что считать мусором. Предположим, мусор возникает когда у нас падает бизнес-логика посреди многоэтапных модификаций. Т.е. обычно ошибок в проде нет, но когда они есть появляется мусор, но не потеря данных.

Топик (он же тред).

По сути это список (vector, array). Если бы был тип данных List, адресуемый ключём (т.е. key=value, где value поддерживает семантику List) то было бы круто.

Для постинга месаги мы говорим push(«7abedf31», «Hello World»), где первый аргумент - имя списка (ключа, хранящего в value список), второй элемент - месага. В конец списка добавляется ещё одна месага.

Редактирование мессаг и хранение версий

Просто редактировать - это update(«7abedf31.5544», «New Value»), где «7abedf31.5544» - имя списка и индекс в нём.

Хранить версии - уже тяжелее. Будем делать так: скажем что наш движок поддерживает списки списков. Тогда мы можем делать push(«7abedf31.5544», «New Value»). То есть, запушить ещё один элемент в конец списка, лежащего в элементе 5544 списка «7abedf31». Там (в элементе 5544) уже лежала строка, так что движок сконвертит её в список с 1 элементом и добавит второй элемент. Можно передать некий флаг разрешающий так делать.

При рисовании страницы треда будем говорить get(«7abedf31», offset = 1000, limit = 25) чтобы получить массив месаг. У списка в движке удобный «индекс», движок за O(1) может обратиться к элементу 1000 и линейно вычитать остальные, т.к. лежит всё это в памяти пластом (вектор). Некоторые вернутые этим запросом элементы будут строками (это месаги без редактирований), а некоторые элементы будут списками (пачки версий) - код бизнес-логики форума нарисует только последний элемент из списка версий, остальные элементы юзает чтобы нарисовать число версий, например и переключалку доступа к нужной версии.

Список топиков.

Это уже просто множество key=value вида, например, «fid_tu_topicname=7abedf31», где fid - ID форума, tu - это время апдейта топика - оно обеспечивает поднятие топика, ибо ключи в лексикографическом порядке сортируются например в B+-tree где хранятся, topicname - ну это название топика.

Если в топик что-то постят, мы тупо делаем INSERT того же самого ключа, но где tu посвежее. В итоге у нас 2 ключа, но это не «неконсистентность», ибо бизнес-логика легко выкинет второй ключ с тем же названием топика, а в value лежит всё тот же указатель на нужный список с мессагами.

Апдейт мессаг

Как описывалось ранее, это один push в подсписок. При чтении треда, где через одно все сообщения имеют по 20 редакций - это неоптимальная хрень, но маловероятная в жизни. Зато при апдейте это всего один push, оставляющий всё в консистентном виде.

Месаги похоже не удаляются. Я смог представить как можно реализовать список в виде совокупности «чанков» в B+-Tree вперемешку с обычными ключами, но не смог придумать как из такого списка дропнуть первый элемент. Ладно, скажем максимум мы можем пометить элемент как удалённый. Нормально, что на какой-то странице ты видишь пробелы вместо сообщений или надпись «НЛО прилетело» - зато страницы не сьезжают - скажем ты дал кому-то ссылку на страницу 176 и она осталась валидной, когда модеры потёрли пару страниц.

MongoDB?

«Заведи в монге документ с кучей списков и херачь в них» - скажет читатель (нормальный читатель скажет вообще не выпёрдываться и взять готовый движок на mysql). Какая у монги будет производительность, если треды будут по 40К страниц (элементов списка). Сколько в секунду можно будет добавить элементов списка в конец? Как быстро оно может достать N элементов с заданным offset?

Телеграм чатик: https://t.me/joinchat/FqPvww9IXM0RmazHBRiamw

Какая у монги будет производительность, если треды будут по 40К страниц (элементов списка). Сколько в секунду можно будет добавить элементов списка в конец? Как быстро оно может достать N элементов с заданным offset?

Можешь решить проблему, материализуя списки в отдельные документы, разбитые по страницам.

i-rinat ★★★★★ ()

Емнип, вот такие ключевые слова тут: nodeca и Vit :)

aol ★★★★★ ()

На подобных задачах вложенные документы нафик не нужны. Сделаешь вложенные документы - встанет раком половина функцций типа пагинации. Поэтому делай структуры примерно как на реляционке и не страдай ерундой.

Какая у монги будет производительность, если треды будут по 40К страниц (элементов списка).

На любой базе жопа будет, если не будешь ручками индекс страниц вести. Т.к. в основном листают вперед-назад, то даже на толстых тредах индекс отстроится постепенно и почти прозрачно. Слетит если модер старые посты удалит, ну отстроится заново. Главное не забыть про эти связи.

Vit ★★★★★ ()

Один писатель и любитель скобок свой форум сделал вообще на файлах.

В добавок написав ненужнолисп на ракетке.

nihirash ★★★ ()
Ответ на: комментарий от Vit

Пагинация не пострадает - одно сообщение форума со всеми его версиями и атрибутами будет стабильно одним объектом.

hlamotron ()
Ответ на: комментарий от hlamotron

Если дергать каждый раз маленький кусочек большого документа, будут заметные потери - больше данных гонять, больше сериализовать, менее эффективный кеш.

Держать историю, которая нафик не нужна, там же где посты, которые дергают постоянно - не рационально.

У тебя везде вложенные документы притянуты за уши.

Vit ★★★★★ ()
Ответ на: комментарий от Vit

Согласен по сути. Просто хотелось не более 1 запроса при апдейте поста. Без возни вида: step1: переложить старую версию в другую табличку, step2: проапдейтить актуальную версию новой версией.

hlamotron ()
Ответ на: комментарий от hlamotron

IMHO ты пытаешься решать задачу снизу вверх - взять какую-то прикольную фичу, а потом силой утоптать в нее все остальное. Это добром никогда не кончается. Ну а конкретно по форуму можешь сорцы нодеки посмотреть на гитхабе. Вот не пригодились там вложенные документы нигде.

Vit ★★★★★ ()
Ответ на: комментарий от nihirash

Один писатель и любитель скобок свой форум сделал вообще на файлах

Надо помнить, что самый первый, UltimateBB, с которого родилось нынешнее представление BB, от классического оформления форумов до BBCode, был как раз на флатфайлах :)

Ну и сегодня флатфайловые форумы, в общем, встречаются в неединичных количествах.

KRoN73 ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.