Управление на сесии в множество нишки/възли

Имаме проблем със споделянето на данни в сесия между много отделни нишки/възли.

Сценарият изглежда така: Има някакъв глобален набор от стойности тип String, например 123ABC-1299AA. Потребителят, когато изпраща команда към приложението, трябва да приеме една от тези стойности. Не може да има две сесии, свързани с една и съща стойност.

В средата имаме 4 сървъра с 50 нишки, чакащи заявки.

Текуща ситуация: Ние съхраняваме в Oracle DataBase стойност за картографиране - сесия. С УНИКАЛНО ограничение на стойността. Когато получим заявка, правим заявка към таблицата за всички стойности и итерираме в пула, като пропускаме използваните стойности, за да намерим една свободна. Ако друга нишка постави нова стойност, докато итерираме, получаваме уникално ограничение и опитваме друго. Също така базата данни е проектирана за някои постоянни данни, този крал на картографирането не е постоянни данни.

Проблеми: Oracle не обработва една малка таблица с огромно количество операции за четене/запис. Състезания за заключване на редове, проблем с повторение на журнала и т.н. Освен когато правим известна поддръжка в базата данни, наблюдаваме изчакване, защото производителността на db намалява.

Изисквания:

  • Една стойност за сесия, без дублиране.
  • Малко време за реакция, под 100ms.
  • Съвместимост на данните във всички възли на приложението.
  • Няма загубено картографиране по време на някакъв вид повреда.
  • Решението трябва да обработва трафик до 100 TPS.

Какво предлагате да използвате в такъв случай?

В момента оценяваме CouchBase за управление на сесии, но има много грешки и лошо възстановяване (може да отнеме до 10 минути).


person voncuver    schedule 25.10.2013    source източник
comment
Не мога да говоря от опит, но някои презентации, които видях на Riak, са супер стабилни и много високоефективни: docs.basho.com/riak/1.4.0/cookbooks/use-cases/session-storage   -  person Alper Akture    schedule 26.10.2013
comment
Couchbase се използва много за този вид употреба. Можете ли да ми дадете повече информация за бъговете, които виждате, и отказите? (сривът е незабавен, това, което може да отнеме известно време в зависимост от вашата конфигурация, е фактът, че системата открива възел надолу)   -  person Tug Grall    schedule 28.10.2013
comment
Нашият проблем с CouchBase е, че когато един възел падне, няма гаранция, че данните ще бъдат последователни след превключване. В момента имаме 2 клъстера с по два възела всеки. Превключването в клъстер е бързо, но превключването между клъстери може да отнеме няколко минути. А също и загуба на данни. За бъгове писахме на Couchbase и те ги коригираха. Или ако е критично, ние го поправяме сами и изпращаме корекция на CB. Основно можем да видим грешки в java-клиента.   -  person voncuver    schedule 29.10.2013


Отговори (2)


Мисля, че не се нуждаете само от добър избор на база данни, но и от известно преструктуриране на приложението. Предполагам, че използвате централизирана база данни на Oracle и всеки от вашите 4 сървъра пише в една и съща база данни. И също така предполагам, че правите балансиране на натоварването от страна на клиента, т.е. вашите клиенти произволно избират един от сървърите за приложения, към който да изпратят заявката.

И така, ето някои от моите мисли за това:

– Защо не разделите базата данни на n сегмента (n = 4 във вашия случай). И накарайте всеки сървър на приложения да гледа собствения си сегмент всеки път, когато дойде нова заявка. Идеята е, че искате да избегнете всякакъв вид спорове. Тук има най-лош сценарий. Какво става, ако се окажете в ситуация, в която всички заявки идват към един от сървърите на приложения и шардът на този сървър на приложения вече е пълен, докато има празни слотове в фрагментите на други слотове. Ако вашите клиенти произволно избират сървър за приложения, ще се оправите. Но все пак бихте искали да се погрижите за горния най-лош сценарий. Така че моето решение за това би било: Ако сървър на приложения осъзнае, че неговият шард е пълен, той произволно ще избере друг фрагмент на друг сървър на приложения и ще поиска този шард за празен слот. Така че забележете, че се озовавате в същата ситуация, в която два сървъра на приложения могат да четат/записват един и същи ред от таблица. Но шансовете това да се случи са намалени с порядъци и вашата архитектура е по-стабилна.

Но можем да направим повече, за да се погрижим за ситуацията, при която 2 сървъра на приложения може да четат/пишат в един и същ шард, защото единият шард на сървъра на приложения е пълен. Ето някои идеи: -- Проверете-след-действайте винаги е проблем във всеки вид система за споделяне на състояние. Така че, ако два сървъра на приложения търсят един и същ шард за празен слот, те ще се конкурират (състезателно състояние). Това, което ще направя в този случай, е да напиша заявката си по такъв начин, че ако текущата стойност е различна от стойността, която прочетох, тогава логиката на моя сървър на приложения ще извърши търсенето отново. Ако текущата стойност е същата като стойността, която прочетох, маркирайте слота като НЕПразен. Моля, обърнете внимание, че трябва да направите това като една и съща транзакция, за да бъде атомарна. Трябва да е нещо като Compare-And-Swap (CAS). Без значение каква база данни използвате SQL или NoSQL, ще трябва да напишете логика във вашето приложение, за да се справите със сценариите Check-Ten-Act в случай на състезателни условия

Също така мисля, че Oracle не е чудесен избор. Първо, скъпо е и второ, изглежда, че всичко, от което се нуждаете, е хранилище за ключ-стойност, така че според мен Oracle е прекален за това. Също така, ако имате една база данни на Oracle, вие имате една точка на отказ там.

Така че като цяло клъстерното (или шардирано) хранилище на ключови стойности е добър подход, който можете да предприемете. Според мен Couchbase не е лош избор. Използвал съм го за управление на широкомащабни сесии. В нашия случай използвахме Moxi за картографиране (за възли на дивана за нас). В нашия случай, ако възелът на couchbase се повреди, на Moxi отне известно време (~ 2-5 минути), за да разбере, че този възел се е повредил и да избере нова главна реплика на couchbase. Но ако вашето приложение е по-чувствително, можете да използвате Couchbase клъстер без Moxi и да запазите логиката на картографиране на заявка към couchbase възел във вашето приложение.

Но в текущия ви сценарий, какво се случва, ако вашата база данни на Oracle спре? Сигурен съм, че времето ви на престой е повече от 3-5 минути. Също така нашето време за преодоляване на срив беше 2-5 минути, защото имахме 90+ couchbase възли. Във вашия случай вероятно ще ви трябват само няколко (4-5) и възстановяването при срив ще бъде за секунди.

Друго нещо, което бих направил във вашия случай е, че бих искал приложението да резервира някои слотове предварително, така че моето четене и писане да стане бързо. Така че, когато приложение има резервирани слотове, тези възли ще бъдат маркирани като „резервирани“. Ако този сървър на приложения някога спре, всички негови запазени възли ще бъдат освободени. Или можете да напишете вашето запитване така

ако сесия == "резервирана" и app_server.health != "АКТИВНА", тогава възелът се счита за свободен.

Така че чрез просто записване на app_server.health = INACTIVE във вашата база данни вие автоматично освобождавате всички маркирани от него възли. Надявам се, че предадох идеята

Мащабирането на инфраструктурата за данни е интересен проблем и нещо, което обичам. Уведомете ме, ако имате въпроси и ще се радвам да помогна.

Основните ми предложения са:

– Не можете ли да предприемете подход, при който използвате GUID за всяка потребителска сесия, вместо да разпределяте предварително изчислен идентификатор на сесия (или стойност) за всеки потребител?

-- Помислете за шардинг. Шардингът не означава преминаване към клъстерен подход. Можете да разделите с в един възел, за да избегнете конфликт между таблиците на базата данни.

-- Оценете NOSQL за ваша употреба. Couchbase (Документен магазин) е добър вариант и съм го използвал за съхраняване на потребителски сесии в голям мащаб. Ако искате да изберете безплатни алтернативи с отворен код, Riak, Redis също са добри. Redis не би предложил вградено клъстериране. Но най-вероятно нямате нужда от него. Redis е супер мощен и ще има много много бързо четене и запис. Twitter използва Redis за съхраняване на туитове на всички потребители.

-- В крайна сметка трябва да управлявате условията на състезание във вашия код. Така че избягвайте условията на състезание, но бъдете готови да се справите с тях, когато се случат

-- Ако имате само една Oracle DB, вече имате единична точка на повреда и вашето време за преход при срив така или иначе ще бъде няколко минути (или часове). Така че не се страхувайте да се впуснете в клъстерирани магазини за ключ-стойност като Couchbase, Voldemort и т.н. За клъстер от 4-5 бележки вашият отказ ще бъде доста бърз (за секунди)

person snegi    schedule 25.10.2013

Точно това е клъстер от 3 възела, с преход към втори клъстер. Oracle беше първият избор, защото е надеждност и последователност на данните.

Споделянето на данни между базата данни е опция, но има проблем, когато един екземпляр не работи по някаква причина. Други ще използват първо своите части и след това ще се опитат да използват 4-та част. Това е проблем, защото този екземпляр ще трябва да проверява всеки път целия си ресурс. Така че получаването на стойност ще бъде много по-бавно. Имахме за цел да получим стойност за по-малко от 0,5 s. Имаме отказ, така че когато един възел падне, няма проблем, защото превключването отне няколко секунди. Проблемът е, когато екземплярът виси (възелът приема заявки, а не обработва) или когато db interconnect е бавен, един възел заключва някои редове, а друг се опитва също да заключи (състезание за необработено заключване).

Относно въпроса: --Трябва да присвоим уникална стойност на сесията; поддържането на цялата тази стойност ще бъде трудно в кода, но е възможно

-- Нашият процес на управление няма да се споразумее за това, сигурност, отказ и т.н.

-- В момента оценявам CouchBase и в момента изглежда добре, но срещнахме проблем с превключването при срив, превключването към друг възел може да отнеме няколко минути и също така няма гаранция, че неуспешният възел ще изчисти данните към втория. Ще прочета за други.

-- С Oracle нашето преминаване към друг клъстер/възел е прозрачно за нас. Най-лошият случай е, когато възелът виси, обикновено поради някои грешки в Oracle. След това имаме около 10 минути, когато 50-80% от трафика се проваля.

Благодаря за отговора, ще оценя задълбочено CB и ще прочета за други решения.

person voncuver    schedule 29.10.2013