6.1 Битката на съкращенията: BASE vs. КИСЕЛИНА
„В химията pH измерва относителната киселинност на воден разтвор. Скалата на pH варира от 0 (силно киселинни вещества) до 14 (силно алкални вещества); чистата вода при 25°C има pH 7 и е неутрална. Инженерите по данни са използвали тази метафора, за да сравнят базите данни по отношение на надеждността на транзакциите." Вероятно идеята е била следната: колкото по-високо е pH, т.е. колкото по-близка е базата данни до "алкална" ("BASE"), толкова по-малко надеждни са транзакциите. |
Популярни релационни бази данни, като MySQL, се появиха точно на базата на ACID. Но през последните десет години така наречените NoSQL бази данни, които комбинират няколко много различни типа бази данни под това име, се справят доста добре без ACID. Всъщност има голям брой разработчици, които работят с NoSQL бази данни и изобщо не се интересуват от транзакциите и тяхната надеждност. Да видим дали са прави.
Не можете да говорите общо за NoSQL базата данни, защото това е просто добра абстракция. NoSQL базите данни се различават една от друга в дизайна на подсистемите за съхранение на данни и дори в моделите на данни: NoSQL е едновременно ориентирана към documentи CouchDB и графична Neo4J. Но ако говорим за тях в контекста на транзакциите, всички те са склонни да бъдат сходни в едно нещо: предоставят ограничени версии на атомарност и изолация и следователно не предоставят гаранции за ACID. За да разберем Howво означава това, нека отговорим на въпроса: Howво предлагат, ако не ACID? Нищо?
Не точно. В крайна сметка те, подобно на релационните бази данни, също трябва да се продават в красива опаковка. И те измислиха собствено "химическо" съкращение - BASE.
6.2 БАЗА като антагонист
И тук отново няма да вървя по буквен ред, а ще започна с фундаменталния термин – консистенция. Ще трябва да изравня вашия ефект на разпознаване, защото тази последователност няма много общо с последователността от ACID. Проблемът с термина последователност е, че се използва в твърде много контексти. Но тази последователност има много по-широк контекст на използване и наистина това е точно последователността, която се обсъжда, когато се обсъждат разпределени системи.
Релационните бази данни, за които говорихме по-горе, предоставят различни нива на изолация на транзакциите и най-строгите от тях гарантират, че една транзакция не може да види невалидни промени, напequalsи от друга транзакция. Ако стоите на касата в магазин и в този момент парите за наема се изтеглят от сметката ви, но транзакцията с превода на парите за наем е неуспешна и сметката ви се връща на предишната си стойност (парите са не е дебитиран), тогава вашата платежна транзакция на касата няма да забележи всички тези жестове - в края на краищата тази транзакция никога не е минала и въз основа на изискването за изолация на транзакциите нейните временни промени не могат да бъдат забелязани от други транзакции.
Много NoSQL бази данни се отказват от гаранцията за изолация и предлагат „евентуална последователност“, при което в крайна сметка ще видите валидни данни, но има шанс транзакцията ви да прочете невалидни стойности – тоест временни, частично актуализирани or остарели. Възможно е данните да станат последователни в "мързелив" режим при четене ("лениво по време на четене").
NoSQL е замислен като база данни за анализи в реално време и за да се постигне по-голяма скорост, те са пожертвали последователност. И Ерик Брюър, същият човек, който измисли термина BASE, формулира така наречената "CAP теорема", според която:
За всяка реализация на разпределено изчисление е възможно да се предоставят не повече от две от следните три свойства:
- съгласуваност на данните ( последователност ) - данните на различни възли (инстанции) не си противоречат;
- наличие ( наличност ) - всяка заявка към разпределена система завършва с правилен отговор, но без гаранция, че отговорите на всички системни възли са еднакви;
- разделителна толерантност (partition tolerance ) - Дори и да няма връзка между възлите, те продължават да работят независимо един от друг.
Ако искате много просто обяснение на CAP, ето ви.
Има мнения, че CAP теоремата не работи и като цяло е формулирана твърде абстрактно. По един or друг начин NoSQL базите данни често отказват последователност в контекста на теоремата за CAP, която описва следната ситуация: данните са актуализирани в клъстер с няколко екземпляра, но промените все още не са синхронизирани във всички екземпляри. Помните ли, споменах примера с DynamoDB по-горе, който ми каза: промените ви станаха трайни - ето HTTP 200 за вас - но видях промените само след 10 секунди? Друг пример от ежедневието на разработчика е DNS, системата за имена на домейни. Ако някой не знае, тогава това е точно „речникът“, който превежда http (s) addressите в IP addressи.
Актуализираният DNS запис се разпространява към сървърите според настройките на интервала на кеширане - така че актуализациите не се забелязват веднага. Е, подобно времево несъответствие (т.е. евентуална съгласуваност) може да се случи с клъстер на релационна база данни (да речем MySQL) - в крайна сметка тази съгласуваност няма нищо общо с консистенцията от ACID. Следователно е важно да се разбере, че в този смисъл базите данни SQL и NoSQL е малко вероятно да се различават много, когато става дума за няколко екземпляра в клъстер.
В допълнение, последователността от край до край може да означава, че заявките за запис ще бъдат напequalsи без ред: т.е. всички данни ще бъдат записани, но стойността, която в крайна сметка ще бъде получена, няма да бъде последната в опашката за запис.
Не-ACID NoSQL базите данни имат така нареченото „меко състояние“ поради модела на съгласуваност от край до край, което означава, че състоянието на системата може да се промени с течение на времето, дори без въвеждане. Но такива системи се стремят да осигурят по-голяма достъпност. Осигуряването на 100% наличност не е тривиална задача, така че говорим за „базова наличност“. И заедно тези три понятия: „основно налични“, „меко състояние“ („меко състояние“) и „евентуална консистенция“ образуват акронима BASE.
Честно казано, концепцията на BASE ми се струва по-празна маркетингова обвивка от ACID - защото не дава нищо ново и не характеризира базата данни по ниHowъв начин. И прикачването на етикети (ACID, BASE, CAP) към определени бази данни може само да обърка разработчиците. Реших все пак да ви запозная с този термин, защото е трудно да го заобиколите, когато изучавате базата данни, но сега, когато знаете Howво е това, искам да го забравите възможно най-скоро. И да се върнем на концепцията за изолацията.
6.3 Значи базите данни BASE изобщо не отговарят на критериите ACID?
По същество там, където ACID базите данни се различават от не-ACID, е, че не-ACID всъщност се отказват от изолация. Това е важно да се разбере. Но още по-важно е да прочетете documentацията на базата данни и да ги тествате по начина, по който правят момчетата от проекта Hermitage. Не е толкова важно How точно създателите на тази or онази база данни наричат своето дете на въображението - ACID or BASE, CAP or не CAP. Важното е Howво точно предоставя тази or онази база данни.
Ако създателите на базата данни твърдят, че предоставя ACID гаранции, тогава вероятно има причина за това, но е препоръчително да я тествате сами, за да разберете дали това е така и до Howва степен. Ако декларират, че тяхната база данни не предоставя такива гаранции, това може да означава следните неща:
-
DB не предоставя гаранция за атомарност. Докато някои NoSQL бази данни предлагат отделен API за атомарни операции (напр. DynamoDB);
- DB не предоставя гаранция за изолация. Това може да означава например, че базата данни няма да записва данните в реда, в който са бor записани.
Що се отнася до гаранцията за издръжливост, много бази данни правят компромис по този въпрос в името на производителността. Записването на диск е твърде дълга операция и има няколко начина за решаване на този проблем. Не искам да навлизам много в теорията на базите данни, но за да разберете приблизително накъде да гледате, ще опиша в общи линии How различните бази данни решават проблема с издръжливостта.
За да сравните различни бази данни, наред с други неща, трябва да знаете Howви структури от данни са в основата на подсистемата за съхранение и извличане на данни на конкретна база данни. Накратко: различните бази данни имат различни реализации на индексиране - тоест организиране на достъпа до данни. Някои от тях ви позволяват да записвате данни по-бързо, други - по-бързо да ги четете. Но не може да се каже като цяло, че някои структури от данни правят издръжливостта по-висока or по-ниска.
6.4 How различните бази данни индексират данните и How това се отразява на издръжливостта и др
Има два основни подхода за съхранение и извличане на данни.
Най-лесният начин да запазите данни е да добавите операции в края на file по подобен на журнал начин (т.е. винаги се извършва операция за добавяне): няма meaning дали искаме да добавим, променим or изтрием данни - всички CRUD операциите просто се записват в дневника. Търсенето в дневника е неефективно и тук се намесва индексът – специална структура от данни, която съхранява метаданни за това къде точно се съхраняват данните. Най-простата стратегия за индексиране на регистрационни файлове е хеш карта, която следи ключовете и стойностите. Стойностите ще бъдат препратки към отместването на byteа за данните, записани във file, който е дневникът (дневник) и се съхранява на диска. Тази структура от данни се съхранява изцяло в паметта, докато самите данни са на диска и се нарича LSM дърво (log структурирано сливане).
Вероятно се чудите: ако записваме операциите си в дневника през цялото време, тогава той ще нарасне прекомерно? Да, и затова е изобретена техниката на уплътняване, която „почиства“ данните с известна периодичност, а именно оставя само най-подходящата стойност за всеки ключ or я изтрива. И ако имаме повече от един лог на диска, но няколко, и всички те са сортирани, тогава ще получим нова структура от данни, наречена SSTable („сортирана table с низове“), и това несъмнено ще подобри нашата производителност. Ако искаме да сортираме в паметта, ще получим подобна структура - така наречената MemTable, но при нея проблемът е, че ако се получи фатален срив на базата данни, тогава записаните последни данни (намират се в MemTable, но все още не са записани в диск) се губят. Всъщност,
Друг подход за индексиране се основава на B-дървета („B-дървета“). В B-дърво данните се записват на диска в страници с фиксиран размер. Тези блокове от данни често са с размер около 4 KB и имат двойки ключ-стойност, сортирани по ключ. Един възел на B-дърво е като масив с връзки към набор от страници. Макс. броят на връзките в масива се нарича фактор на разклоняване. Всеки диапазон от страници е друг възел на B-дърво с връзки към други диапазони от страници.
В крайна сметка на ниво лист ще намерите отделни страници. Тази идея е подобна на указателите в езиците за програмиране на ниско ниво, с изключение на това, че тези препратки към страници се съхраняват на диска, а не в паметта. Когато се появят INSERT и DELETE в базата данни, тогава някои възли могат да се разделят на две поддървета, за да съответстват на фактора на разклоняване. Ако базата данни се провали по няHowва причина по средата на процеса, целостта на данните може да бъде компрометирана. За да се предотврати това да се случи, базите данни, използващи B-дървета, поддържат "дневник за предварително записване" or WAL, в който се записва всяка отделна транзакция. Този WAL се използва за възстановяване на състоянието на B-дървото, ако то е повредено. И изглежда, че това прави базите данни, използващи B-дървета, по-добри по отношение на издръжливостта. Но базите данни, базирани на LSM, също могат да поддържат файл, който по същество изпълнява същата функция като WAL. Затова ще повторя това, което вече казах и може би повече от веднъж: разберете механизмите на работа на базата данни, която сте избрали.
Това, което е сигурно за B-дърветата обаче, е, че те са добри за транзакционността: всеки ключ се среща само на едно място в индекса, докато журналираните подсистеми за съхранение могат да имат множество копия на един и същ ключ в различни шардове (например, докато се извършва следващо уплътняване).
Дизайнът на индекса обаче пряко влияе върху производителността на базата данни. При LSM дърво записите на диск са последователни и B-дърветата предизвикват множество произволни достъпи до диска, така че операциите по запис са по-бързи с LSM, отколкото с B-дървета. Разликата е особено значима за магнитните твърди дискове (HDD), където последователните записи са много по-бързи от случайните записи. Четенето е по-бавно на LSM дървета, защото трябва да прегледате няколко различни структури от данни и SS таблици, които са на различни етапи на уплътняване. По-подробно изглежда така. Ако направим проста заявка към база данни с LSM, първо ще потърсим ключа в MemTable. Ако не е там, разглеждаме най-новата SSTable; ако не е там, тогава разглеждаме предпоследната SSTable и т.н. Ако исканият ключ не съществува, тогава с LSM ще знаем това последно. LSM дървета се използват например в: LevelDB, RocksDB, Cassandra и HBase.
Описвам всичко толкова подробно, за да разберете, че когато избирате база данни, трябва да имате предвид много различни неща: например очаквате ли да пишете or четете данни повече. И все още не съм споменал разликата в моделите на данни (трябва ли да обхождате данните, Howто позволява графичният модел? Има ли изобщо връзки между различни единици във вашите данни - тогава релационните бази данни ще дойдат на помощ?), и 2 типа схеми на данни - при писане (Howто в много NoSQL) и четене (Howто в релационни).
Ако се върнем към аспекта на издръжливостта, тогава заключението ще бъде следното: всяка база данни, която записва на диск, независимо от механизмите за индексиране, може да осигури добри гаранции за издръжливостта на вашите данни, но трябва да се справите с всяка конкретна база данни , Howво точно предлага.
6.5 Как работят DBs в паметта
Между другото, освен базите данни, които записват на диск, има и така наречените бази данни "в паметта", които работят предимно с RAM. Накратко, базите данни в паметта обикновено предлагат по-ниска издръжливост в името на по-бързите скорости на запис и четене, но това може да е подходящо за някои applications.
Факт е, че RAM паметта отдавна е по-скъпа от дисковете, но напоследък започна бързо да поевтинява, което доведе до появата на нов тип база данни - което е логично, като се има предвид скоростта на четене и запис на данни от RAM. Но с право ще попитате: Howво ще кажете за безопасността на данните в тези бази данни? Тук отново трябва да разгледате детайлите на изпълнението. Като цяло разработчиците на такива бази данни предлагат следните механизми:
- Можете да използвате RAM, захранван от батерии;
- Възможно е да се записват журнали за промени на диск (нещо като споменатите по-горе WAL), но не и самите данни;
- Можете периодично да записвате копия на състоянието на базата данни на диск (което, без да използвате други опции, не дава гаранция, а само подобрява издръжливостта);
- Можете да копирате състоянието на RAM на други машини.
Например базата данни Redis в паметта, която се използва главно като опашка за съобщения or кеш, няма издръжливост от ACID: тя не гарантира, че успешно изпълнена команда ще бъде съхранена на диска, тъй като Redis изхвърля данните на диска (ако имат активирано постоянство) само асинхронно, на редовни интервали.
Това обаче не е критично за всички applications: намерих пример за кооперативния онлайн редактор на EtherPad, който се изтрива на всеки 1-2 секунди и потенциално потребителят може да загуби няколко букви or дума, което едва ли е критично. В противен случай, тъй като базите данни в паметта са добри с това, че предоставят модели на данни, които биха бor трудни за прилагане с дискови индекси, Redis може да се използва за внедряване на транзакции - неговата опашка с приоритет ви позволява да направите това.