LINUX.ORG.RU

Подскажите нормальную БД для которой существует неблокирующий сишный API

 , , ,


4

4

Суть — доступ к базе в event-loop при большом количестве входящих http соединений — over 30k.

event-loop подразумевается на базе libuv.

★★★★★

Мне кажется прям совсем совсем неблокирующих не существует. А если существует то будут выстраиваться километровые очереди для последующей выборки и синхронизации при этом где то 10536`е соединение будет ждать чтения пока в 856 параллельных потоках разруляться зависимости очерёдности записи в одно и тоже место .

sqlite умеет в многопоток, но каждый поток должен ждать своей очереди на транзикацию. По остальным хз. Подписался.

Херач отдельную sqlite на каждого реганого клиента. Ну и пусть что 10000 баз будет =) Зато вжжууух… и иноды кончились

LINUX-ORG-RU ()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)

В первую очередь нужно задаться вопросом а выдержит ли СУБД такое кол-во одновременных соединений. Большинство СУБД не имеют аналогов event loop и тупо создают для кадого клиента процесс или поток, т.е. соединение для них весьма дорогое. И скорее всего СУБД раньше сдохнет от конкуренции за IOPSы.

Далее, если для СУБД нет подходящего клиента, разумно делать примерно как делает СУБД - т.е. если создаёт поток или процесс, то и у себя создаешь пул потоков с клиентами, а из event loop общаешься с ним очередями. Если СУБД распределённая, то для прикручивания асинхронности к сервису можно даже сделать несколько машин с такими сервисами.

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

Вы неправильно поняли вопрос. Неблокирующий сишный API как раз и позволяет имея 100500+ входящих http соединений не создавать столько-же исходящих к БД.

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

Вовсе нет, неблокирующй API это асинхронный API, а ты хочешь мультиплексирование через одно соединение. Мультиплексирование и асинхронность фичи ортогональные.

Но это не важно, потому что всё в конечном счёте сводится к возможностям СУБД. Однонодовая однодисковая СУБД не потянет одновременно 100500+ запросов.

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

Вовсе нет, неблокирующй API это асинхронный API, а ты хочешь мультиплексирование через одно соединение.

Извиняюсь, но вы путаетесь в терминологии. Вы наверное недавно пришли с Windows, в которой нет понятия неблокирующего API?

cvv ★★★★★ ()

я на какую-то странную х-ню в libuv наступила. иногда (когда точно, я так и не поняла) там при множестве повторных tcp соединений таймауты глючили. я пыталась дебажить, но пока не докопалась до сути проблемы. проблема возникала редко и только если соединений дофига.

Iron_Bug ★★★★ ()
Последнее исправление: Iron_Bug (всего исправлений: 1)

а насчёт БД - в каком смысле неблокирующий? сама БД если имеет констрейнты, то там всё равно будет блокирование. а так прикрути любые очереди и сри в очередь, а на другом конце сбрасывай в базу. никаких проблем.

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

не знаю. я бы не использовала ничего, если честно. для крупных проектов всегда писали сами всё с нуля. я просто переделывала чужую поделку и там с livbuv столкнулась. я ещё попробую подебажить и как-то на искусственном примере создать прецедент с таймерами, но это геморно. там проблема была в том, что при обращении с одного IP повторные TCP сессии не устанавливались и отваливались по таймауту. а происходило это из-за таймеров внутри libuv, хотя пакеты все ходили нормально, это я проверяла.

Iron_Bug ★★★★ ()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Ответ на: комментарий от Iron_Bug

проблема была в том, что при обращении с одного IP повторные TCP сессии не устанавливались и отваливались по таймауту

Исчерпывалась очередь pending connections, accept() не успевали разгребать соединения? Только непонятно, причем тут обращения именно с одного IP…

Sorcerer ★★★★★ ()
Последнее исправление: Sorcerer (всего исправлений: 1)
Ответ на: комментарий от cvv

Извиняюсь, но вы путаетесь в терминологии. Вы наверное недавно пришли с Windows, в которой нет понятия неблокирующего API?

Везде оно есть. Неблокирующее API лишь возвращает ошибку в случае, если состояние таково, что данные не могут быть прочитаны. Вся логика по работе с состоянием перекладывается на пользовательский код, вместо блокировок в ядре. Ты действительно хочешь мультиплексирование. Складывай запросы в очередь, разгребай ее в отдельном треде, а дальше складывай ответы в другую очередь.

xpahos ★★★★★ ()

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

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

Не понимаю зачем тут вообще очереди. Есть аппликуха фасад, которая принимает хттп несколькими потоками воркерами. Эти воркеры пишут в БД синхронно или асинхронно (надо тестить что лучше). Роль очереди берет на себя система реализации сокетов. Всё.

q0tw4 ★★★★ ()
Последнее исправление: q0tw4 (всего исправлений: 1)
Ответ на: комментарий от q0tw4

Не понимаю зачем тут вообще очереди. Есть аппликуха фасад, которая принимает хттп несколькими потоками воркерами. Эти воркеры пишут в БД синхронно или асинхронно (надо тестить что лучше). Роль очереди берет на себя система реализации сокетов. Всё.

Как определить в какой контекст отдать данные после текущего чтения?

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

Вопервых работать с БД можно синхронно. Других клиентов обслужат другие воркеры. Очередью будет хттп сокет. Во-вторых можно формировать SQL так, чтоб из ответа был понятен контекст (SELECT $requestId, data). Да мало ли еще способов в зависимости от конкретики задачи

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

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

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

Вопервых работать с БД можно синхронно.

В event loop работать с БД синхронно?

Других клиентов обслужат другие воркеры.

Зачем тогда event loop?

Во-вторых можно формировать SQL так, чтоб из ответа был понятен контекст (SELECT $requestId, data).

Еще можно придумать кучу способов выдать свой бред за что-то нормальное.

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

Ну ок. Это не ивент луп, а просто тредпул. Просто, удобно и совместимо.

Это совсем другая модель работы и совсем другое поведение. Оно не проще, не удобнее, на совместимость не влияет.

Ну или пишите на расте, там всё через tokio можно пустить

При чем тут Rust? Это такая же библиотека, как libuv, libevent или самописный обработчик на epoll/kqueue/select.

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

Это такая же библиотека, как libuv

Разница в том, что под libuv и прочие поделки никто не пишет либы разных протоколов (ну по крайней мере на сайте БД вряд ли будут лежать либы, работающие через васин ивентлуп). А в расте tokio - стандарт. Почти для каждого протокола Х, для которого есть синхронный крейт находится человек, оборачивающий данный протокол в tokio.

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

Во-вторых можно формировать SQL так, чтоб из ответа был понятен контекст (SELECT $requestId, data).

Еще можно придумать кучу способов выдать свой бред за что-то нормальное.

Даже почта по IMAP работает асинхронно. К каждому запросу есть ID, который возвращается в соответствующем ответе.

gag ★★★★★ ()
Последнее исправление: gag (всего исправлений: 1)
Ответ на: комментарий от anonymous

при большом количестве входящих http соединений — over 30k.

Однонодовая однодисковая СУБД не потянет одновременно 100500+ запросов.

Даже у десктопных PCIe NVMe SSD 600000 4K IOPS. Почему бы и нет.

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

Разница в том, что под libuv и прочие поделки никто не пишет либы разных протоколов (ну по крайней мере на сайте БД вряд ли будут лежать либы, работающие через васин ивентлуп).

Все адекватные разработчики — пишут.

cvv ★★★★★ ()

Не всё так просто. Надо ставить несколько инстансов субд и уже к ним коннектиться из пулла коннектов, а к пулу обращаться из libuv loop. А лучше взять Node.js 😀

menangen ★★★★★ ()

redis йопта!

А ваще, ты как себе представляешь 30k стуков об базу, какая бы она не была - это диск - это просадка.

Нужно брать прокладку на с++( некий деман ) в нём держать всю базу в раме, и по таймауту - сохраняца в базу на диск.

Если рамы не хватает - докупать.

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

А ваще, ты как себе представляешь 30k стуков об базу, какая бы она не была - это диск - это просадка.

реальные проблемы у Постгреса начинаются после 100к, тем не менее некоторым удается получить несколько миллионов инсертов в секунду.

cvv ★★★★★ ()
Последнее исправление: cvv (всего исправлений: 1)
Ответ на: комментарий от gag

Даже почта по IMAP работает асинхронно. К каждому запросу есть ID, который возвращается в соответствующем ответе.

Я много могу назвать протоколов асинхронных. Но они не предназначены для near real-time запросов к СУБД. API в таком виде не очень хороший вариант.

xpahos ★★★★★ ()