В тази статия съм събрал първите 3 поста в моя блог (1 2 3), в които обсъждам зараждането на Oracle RAC. Продължението, в което ще задълбая в синхронизацията, заключванията, Cache Fusion и Global Resource Directory ще сложа в отделна статия по-късно.
Основни понятия в клъстерната архитектура
Първо трябва да изчистим идеята за клъстер. Според Wikipedia, “A computer cluster is a group of tightly coupled computers that work together closely so that in many respects they can be viewed as though they are a single computer”. Друга, по-ясна дефиниция е „A cluster environment is defined as a system built with a multitude of nodes sharing local resources (Disks, CPU power, Printer queues…) and offering cluster-wide services (Security, Synchronization, Communication)”. Като цяло идеята е да се извършва една обща работа на няколко компютъра (наречени cluster nodes, или възли), които от гледна точка на потребителя/клиента изглеждат като един (ресурс).
В началото искам да уточня някои термини, които ще използвам.
- Node (възел): това е един от „компютрите”, които формират клъстера. Представлява относително самостоятелна единица със собствени процесори и памет.
- Shared resource (споделен ресурс): това е ресурс, който се споделя между възлите в клъстера. Обикновено е общ дисков масив.
- Пакет: за да се извършва работата паралелно, тя трябва да (може да) се раздели на пакети, които могат да се обработят самостоятелно. Пакета е единица работа, която се извършва винаги само от един от възлите.
Има няколко вида клъстерни архитектури, които представят различни предимства:
- Share Nothing Clusters: това са системи, в които всеки възел управлява ексклузивно част от споделения ресурс (примерно дял от споделения диск). В този случай ресурсите са споделени само на хардуерно ниво (или изобщо не са споделени), но логически са разделени. Това е най-лесният за реализиране вариант, но е най-труден за използване. Данните са стриктно разпределени между възлите, като всеки има достъп само до своите данни. Пример: IBM SP2, Terradata, Informix OnLine XPS
- Shared Disk Cluster: Това е частен случай, в който не се получава по-висока производителност, а само отказоустойчивост. Даннтие са на споделен диск, но е активен само един възел който има екслкузивен достъп до тях. При отпадане на активния възел, работата се прехвърля към неактивния, който до тогава не е работил. Такива решения са повечето клъстерирания на приложение на ниво ОС: HP ServiceGuard, Veritas Cluster Server, Microsoft Cluster Server
- Shared Everything Clusters: това са системи, в които общия ресурс се управлява равноправно от всичките възли на клъстера. В този случай всеки от възлите може да обработи всеки от пакетите, т.е. потребителя не се интересува към кой възел е закачен в момента. Това предоставя много предимства за клиентското приложение и значително го опростява. От друга страна такъв клъстер е труден за реализиране и усложнява значително задачата за синхронизация между възлите. Може да се получи много висока производителност и отказоустойчивост, почти перфектен load balancing (разпределение на натоварването между възлите). Могат да се добавят и премахват възли динамично, като това не прекъсва достъпноста на данните. Пример са Oracle RAC, IBM HACMP
- NUMA (Non Uniform Memory Access) – NUMA е подход за изграждане на клъстер от силно специализирани хардуерни компоненти. Клъстеризирането се извършва на ниво преди операционната система от едно ниво което извършва абстракция на хардуера и предоставя на ОС ресурси като дискове, процесори, памет. При този подход не е задължително да се прави синхронизация на работните пакети. Недостатък е, че има изявена латентност при достъп до „отдалечен ресурс” (примерно процесор от един блок чете памет от друг блок). Тази латентност се избягва до колкото е възможно от ОС при разпределението на ресурсите (ако ОС е запозната с NUMA архитектурата).
Каква е целта, която се преследва с клъстеризирането?
- Отказоустойчивост: в един shared everything или NUMA клъстер, където всеки възел може да свърши всяка работа, отпадането на един възел не води до отпадане на приложението като цяло.
- Скалируемост: както при всяко решение за паралелизация на задачи, търси се повишаване на производителността. Идеята е, че съвкупността от много възли е по-производителна и от най-мощния единичен възел. Теоретично производителността на клъстера може да се изрази като
T(N) = SUM t(i)
i=1->N
Където
N е броя на възлите,
t(i) е производителността на i-тия възел.
На практика се получава загуба на производителност от нуждата за синхронизация между възлите. Това може да се изрази така (за хомогенен клъстер)
T(N) = N*t*s(N)
Където
N е броя на възлите
t е производителността на 1 възел
s(N) e коефициент на синхронизацията. Тук важи 0 < s(N) <= 1
Целта на клъстерните решения е да доближат s(N) до 1, т.е. да се получи почти линейна скалируемост: двойно повече възли водят до двойно по-голяма производителност. Тук може да се каже, че когато s(N) > 1/N, приложението се скалира добре. Колкото по-блозо е s(N) до 1, толкова по-добре скалира приложението. Когато s(N) < 1/N, приложението не скалира добре – при добавяне на възли в клъстера общата производителност пада.
Факторите, които влияят върху s(N) са:
- Clusterware – това е системата, която предоставя клъстерните услуги; грижи се за синхронизацията и заключванията. Такъв софтуер е Oracle CRS (Cluster ready Services, “сърцето” на Oracle RAC).
- Application – самото приложение, което използва БД.
- Топологията на клъстера (предимно типа на връзката между възлите)
В началото бе OPS
Трудно се започва от определена точка. Може би корена е дълбоко забит в MPP (massive parallel processing) идеите, които по-късно се прекръщават на clustering. Там силните на деня (в края на 70-те години) са DEC, IBM и Cray. Може би първият успешен клъстер е ARCnet, създаден от DataPiont през 1977. Той е бил подходящ за изследователски цели, помагал е на университети, но не се е наложил като търговки продукт.
Първи комерсиален успех постигат DEC с техния VAX cluster в началото на 80-те. Той е работил върху VAX/VMS и освен изчислителна мощ е разпределял и файлове, и периферни устройства. За съжаление управлението на разпределените заключвания при него (DLM, Distributed Lock Management) е оптимизирано за работа с относително малко на брой ресурси (примерно файлове и устройства), а не за хиляди и десетки хиляди буфери в Buffer cache на СУБД. Той „не скалира добре”.
За това Oracle, когато решават да създадат СУБД, която да може да работи в този клъстерен режим, си създават собствен DLM. Това става по времето на версия 6 на Oracle database. В началото това е предизвикало недоумение – да си създаваш свой DLM вместо да използваш този на DEC? В крайна сметка DEC са основоположници на цялата клъстерна идея, техния продукт е доста успешен!
Но се ражда Oracle 6.35 (преименуван на 6.2 за да се отпразнува светлия празник) с неговия Oracle Parallel Server (OPS) – първата клъстерна БД. Оказва се, че DLM на Oracle работи много добре с VAX клъстерите на Digital. Всъщност работи толкова добре, че самите DEC го вземат и го добавят като част от техния клъстерен стек. Така когато излиза Oracle 7, той отново работи с вградения DLM на Digital.
В началото на 90-те много варианти на UNIX въвеждат възможност за клъстеризация. Те се базират основно на DLM от Oracle. Дори Microsoft правят стъпки в тази посока (но техния DLM не е взет от Oracle – не, той е от Digital ). В това време Oracle 7 използва клъстерния стек на ОС и така доставя тази услуга под различните UNIX платформи. За съжаление инсталацията и настройката на OPS е доста сложна, защото се синхронизират множество слоеве от различни доставчици.
Когато на бял свят излиза Oracle 8, в него има общ lock manager, който е явна индикация, че Oracle подготвят собствен клъстерен стек. Lock manager-а е в кода на СУБД като има малка част OSD (Operating-system dependent) код. По този начин може да се гарантира еднакво поведение на всякакви платформи. По-късно този код влиза като част от ядрото на Oracle и е познат като IDLM (Integrated Distributed Lock Manager).
Oracle 9i RAC използва този собствен IDLM при всички платвофими, но разчита на външен clusterware (освен под Linux и Windows). Във версия 10g вече целият стек се доставя от Oracle (въпреки че пак е възможно да се интегрира с външен Cluster manager).
За да се клъстеризира една БД с помощта на OPS са необходими следните „нива”:
- Cluster manager – наблюдава възлите на клъстера, грижи се за синхронизацията между тях, предприема необходимите стъпки ако някой възел „отпадне”. Той е в OSD слоя и (обикновено) се доставя от доставчика на ОС. Пример за такъв софтуер са Sun Cluster (за Solaris), Service Guard (за HP UX), HACMP (за IBM AIX)
- Distributed Lock Manager – отговаря за заключванията, чрез които се постига консистентност и интегритет на БД. Грижи се до всеки общ ресурс да има достъп само от един възел в един момент. Не отговаря за транзакционните (потребителски) заключвания
- Cluster interconnect - осигурява мрежовата връзка между възлите в клъстера. В началот се използва за обмен на съобщения.
- Shared Disk array - съдържа споделените файлове с данни
DLM, PCM, Ping, Cache Fusion
Първото изискване към една база от данни е да предоставя механизъм за гарантиране на консистентността на данните в нея. Това е по-важно от скорост на обработка лекота на работата.
При „еднопотребителски” системи това е лесно – няма нужда от синхронизация. Всичко се случва серийно и единствената заплаха за интегритета са неочакваните грешки, които могат да се предотвратят с елементарни трназакционни механизми.
Когато БД стане многопотребителска, много процеси трябва да си споделят достъпа до данните и всеки да вижда и променя точно каквото трябва. Недопустимо е един атомарен ресурс (примерно ред от таблица) да бъде променян от два процеса едновременно. Това увеличава значително сложността на транзакционните механизми и поставя изискване от заключвания, които да сериализират достъпа. Някои СУБД и сега не се справят успешно с това и предоставят „груб” lock management (примерно заключване при четене, ескалиране на заключването, понеже е скъп ресурс и т.н.). Въпреки това успяват да гарантират консистентност, макар и на цената на намалена скалируемост. Едно от най-гениалните и печеливши парчета в кода на Oracle е страхотното управление на транзакции (родено в дебрите на Oracle 4!).
За да се клъстеризира една БД вече трябва още едно ниво на управление на ресусрите. Това е т.нар. Distributed Lock Manager. Той гарантира, че един обект (примерно блок с данни) може в даден момент да бъде променян само от един възел в клъстера. Това е цяло ново ниво на сложност. DLM няма нищо общо с транзакциите на потребителите. Напълно допустимо е в един блок да има ред, заключен от процес (сесия) работеща на node 1 докато самия блок в даден момент е заключен от node 4.
DLM управлява (основно) блокове в buffer cache. В не-клъстерна среда, ако един процес на един има нужда да прочете или промени даден блок, той поглежда дали е наличен в buffer cache (виж “Четене на данни в Oracle”). Ако не е, прочита го от диска, променя го и готово. Ако някой друг го е променил преди това, то или промените са в Buffer cache (и се работи директно там), или са записани на диска и ще бъдат прочетени.
В клъстерна среда всеки възел си има свой buffer cache. Следователно имаме реална възможност един блок да бъде прочетен и променен от друг възел. В такъв случай дори ако имаме негово старо копие в локалния buffer cache, ще получим неконсистентен изглед на данните. За да се избегне този проблем се въвежда т.нар. PCM (Parallel Cache Management).
Има 3 възможни случая на споделен блок.
- read/read. Тук няма конфликт, понеже няма промяна на данните. Възел 1 прочита блока и по този начин става негов собственик. Когато възел 2 иска да го прочете, няма нужда от намеса на PCM
- read/write. Възел 1 е модифицирал блок, който възел 2 иска да прочете. В старите версии на Oracle (преди 8i), възел 1 трябва да запише блока на общия дисков масив, за да може възел 2 да го прочете. Това е т. нар. ping и е най-голямата пречка за производителността на OPS.
В Oracle 8i се въвежда т. нар Cache Fusion Phase 1. Това е механизъм, при който един допълнителен процес (Block Server Process, BSP) изгражда консистентно копие на блока (CU) във възел 1 и го изпраща на възел 2 през interconnect връзката. По този начин се избягва Ping.
- write/write. В този случай възел 2 иска да модифицира блок, който е модифициран от възел 1. Във Oracle 8i при възникване на такъв случай възел 1 трябва да „отключи” блока и да направи ping, за да може възел 2 да го прочете и заключи. Това е сериозна пречка за скалируемост на OLTP системи, в които често се налага един блок да бъде променян от 2 възела. Във Oracle 9i/10g RAC с появата на Cache Fusion Phase 2 това вече е преодоляно. При Cache Fusion Phase 2 през interconnect се предават като CR, така и CUR варианти на блока и се синхронизира успешно работата без Ping
Явор |