HBase
 sql >> база данни >  >> NoSQL >> HBase

Вътре в архитектурата на Santander за поглъщане на данни в почти реално време (част 2)

Благодаря на Педро Боадо и Абел Фернандес Алфонсо от инженерния екип на Сантандер за сътрудничеството им в тази публикация за това как Santander UK използва Apache HBase като двигател за обслужване в почти реално време за захранване на своето иновативно приложение Spendlytics.

Приложението Spendlytics за iOS е предназначено да помогне на клиентите с лични дебитни и кредитни карти на Santander да поддържат разходите си, включително плащания, направени чрез Apple Pay. Той използва данни за транзакциите в реално време, за да даде възможност на клиентите да анализират разходите по картата си през периоди от време (седмично, месечно, годишно), по категории (пътувания, супермаркети, пари в брой и т.н.) и по търговец на дребно.

В предишната ни публикация описахме как Apache Flume и Apache Kafka се използват за трансформиране, обогатяване и поточно предаване на транзакции в Apache HBase. Тази публикация продължава, като описва как транзакциите са подредени в Apache HBase за оптимизиране на производителността и как използваме копроцесори, за да предоставим агрегации на потребителски тенденции при закупуване. Santander и Cloudera продължиха (и все още са) пътешествие с HBase със Spendlytics, което е видяло много итерации и оптимизации на дизайна на схеми и реализациите на копроцесора. Надяваме се, че тези научени уроци са основните изводи от тази публикация.

Схема 1.0

Добрият дизайн на схема на HBase е свързан с разбирането на планираните модели на достъп. Направете го правилно и HBase ще лети; сбъркайте и може да се окажете с неоптимална производителност поради компромиси в дизайна като регионални горещи точки или трябва да извършвате големи сканирания в множество региони. (гореща точка в таблица на HBase е мястото, където неравномерното разпределение на rowkey може да доведе до пренасочване на по-голямата част от заявките към един регион, което претоварва RegionServer и води до бавно време за реакция.)

Какво знаехме за моделите за достъп, предназначени за Spendlytics и как те повлияха на първоначалния дизайн на схемата:

  • Клиентите анализират само транзакции по собствените си сметки:
    • За бързо изпълнение на линейно сканиране всички клиентски транзакции трябва да се съхраняват последователно.
  • Идентификаторите на клиенти се увеличават монотонно:
    • Последователните идентификатори на клиенти увеличават вероятността по-нови клиенти да бъдат разположени съвместно в рамките на един и същи регион, което потенциално създава гореща точка в региона. За да се избегне този проблем, идентификаторите на клиенти трябва да бъдат подсолени (с префикс) или обърнати към равномерно разпределение в региони, когато се използват в началото на клавиша за ред.
  • Клиентите имат няколко карти
    • За да се оптимизират сканирането, транзакциите на клиента трябва да бъдат допълнително групирани и сортирани по договор с карта, т.е. идентификационният номер на договора трябва да представлява част от клавиша за редове.
  • Транзакциите ще бъдат достъпни в тяхната цялост, т.е. атрибути като търговец на дребно, търговец, местоположение, валута и сума не е необходимо да се четат отделно
    • Съхраняването на атрибути на транзакции в отделни клетки ще доведе до по-широка, рядка таблица, което ще увеличи времето за търсене. Тъй като атрибутите ще бъдат достъпни заедно, има смисъл да ги сериализирате заедно в Apache Avro запис. Avro е компактен и ни предоставя ефективно представяне с възможност за развитие на схемата.
  • Транзакциите са достъпни поотделно, на партиди (по време, категория и търговец на дребно) и по съвкупност (по време, категория и търговец).
    • Добавянето на уникален идентификационен номер на транзакцията като квалификатор на колона ще позволи извличане на отделни транзакции, без да се добавя повече сложност към клавишния ред.
    • За да се даде възможност за бързо сканиране на транзакции през променливи периоди от време, клеймото за време на транзакцията трябва да е част от клавиша за редове.
    • Добавянето на категория и търговец на дребно към rowkey може да бъде твърде детайлно и би довело до много висока и тясна таблица със сложен ключ за ред. Високите и тесните са добре, като се има предвид, че атомарността не е проблем, но наличието им като квалификатори на колони би разширило таблицата, като същевременно поддържа вторични агрегации.
  • Данните за тенденцията трябва да бъдат предварително изчислени, доколкото е възможно, за да се оптимизира производителността на четене.
    • Повече за това по-късно, но засега знайте, че добавихме второ семейство колони, за да съхраняваме тенденциите.

    Въз основа на горното, първоначалният дизайн на схемата е илюстриран по следния начин:

    Изчислителни тенденции

    Аспектът на първоначалния дизайн, от който научихме най-много, беше изчислителните тенденции. Изискването беше да се даде възможност на клиентите да анализират разходите си по категории и търговци на дребно до час. Точките от данни включват най-малката и най-голямата стойност на транзакциите, общата стойност на транзакцията и броя на транзакциите. Времето за реакция трябваше да бъде 200 ms или по-малко.

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

    Експериментирахме с различни дизайни на схеми и се опитахме да използваме някои добре познати дизайни, където е възможно (като схемата на OpenTSDB). След няколко итерации се спряхме на дизайна на схемата, илюстриран по-горе. Съхранени в таблицата на транзакциите, в отделно семейство колони, стойностите на тенденциите са организирани заедно в един ред, с един ред за тенденция на клиент. Като дадете на rowkey същия префикс като транзакциите на клиента (например <reverse_customer_id>::<contract_id> ) гарантира, че редът за тенденция ще бъде сортиран заедно със съответните записи за транзакции на клиента. С дефинирани граници на региони и персонализирана политика за разделяне на региони, ние също можем да гарантираме, че редът за тенденция винаги ще бъде разположен заедно със записите на транзакциите на клиента, което позволява агрегирането на тенденциите да остане изцяло от страна на сървъра в копроцесора.

    За предварително изчисление на тенденциите внедрихме персонализиран копроцесор за наблюдател за да се присъедините към пътя за запис. (Копроцесорите на Observer са подобни на тригерите в RDBMS по това, че изпълняват потребителски код преди или след възникване на конкретно събитие. Например, пред или след Put или Get .)

    На postPut копроцесорът извършва следните действия:

    1. Проверява Put за атрибут на тенденция (флаг). Атрибутът се задава само за нови записи на транзакции, за да се избегнат рекурсивни повиквания при актуализиране на записа за тенденция. Освен това позволява копроцесорът да бъде пропуснат за Put които не изискват актуализиране на тенденциите (напр. селища ).
    2. Вземете запис на тенденция за клиента. Записът за тенденция на клиента се локализира заедно с техните транзакции (въз основа на префикса на rowkey), така че копроцесорът може да го извлече директно от текущия регион. Редът на тенденцията трябва да бъде заключен, за да се предотврати множеството нишки на манипулатора на RegionServer, които се опитват да актуализират тенденциите паралелно.
    3. Актуализиране на точките от данни:
    4. Актуализиране и отключване на реда с тенденция.

    Решението се оказа точно по време на тестване и, както се очакваше, производителността на четене надхвърли изискванията. Въпреки това имаше някои опасения относно този подход. Първият беше как да се справим с провала:тенденциите се съхраняват в отделен ред, така че атомарността не може да бъде гарантирана. Вторият беше как да се потвърди точността на тенденциите във времето; тоест ще трябва да приложим механизъм за идентифициране и отстраняване на всякакви неточности в тенденцията. Когато разгледахме и изискванията за HA и факта, че ще трябва да стартираме две активно-активни копия на HBase в различни центрове за данни, това може да бъде по-голям проблем. Точността на тенденцията не само може да намалее с течение на времето, но двата клъстера също могат да се отклоняват и да трябва да бъдат съгласувани в зависимост от метода, който използвахме, за да ги синхронизираме. И накрая, коригирането на грешки или добавянето на нови точки от данни би било трудно, защото вероятно ще трябва да върнем назад и да преизчислим всички тенденции.

    След това имаше изпълнение на писане. За всяка нова транзакция наблюдателят трябваше да извлече тренд запис, да актуализира 32 точки от данни и да върне записа на тенденцията обратно. Въпреки всичко това, което се случва в рамките на един регион, открихме, че пропускателната способност е намалена от над 20 000 записа в секунда до 1000 записа в секунда (на RegionServer). Тази производителност беше приемлива в краткосрочен план, но нямаше да се мащабира, за да поддържа прогнозираното дългосрочно натоварване.

    Знаехме, че производителността на запис е риск, така че имахме резервен план и това беше копроцесор за крайна точка . Копроцесорите на крайната точка са подобни на съхранените процедури в RDBMS, тъй като ви позволяват да извършвате изчисления от страна на сървъра – в RegionServer, където се намират данните, а не в клиента. Крайните точки ефективно разширяват HBase API.

    Вместо предварително изчисляване на тенденциите, крайната точка ги изчислява в движение, от страна на сървъра. В резултат на това бихме могли да изхвърлим семейството колони за тенденции от схемата и рискът от неточности и отклонения да отиде с него. Отдалечаването от наблюдателя доведе до добра производителност на запис, но дали четенето ще бъде достатъчно бързо? Накратко, да. С транзакциите на клиента, ограничени до един регион и сортирани по карта и времеви печат, крайната точка може да сканира и обобщава бързо, в рамките на целта от 200 мс на Spendlytics. Това също означава, че клиентска заявка (от Spendlytics API в този случай) се насочва само към един екземпляр на крайна точка (единичен RegionServer) и клиентът ще получи един единствен отговор обратно с пълен резултат – тоест без клиентска страна обработката е необходима за обобщаване на частични резултати от множество крайни точки, което би било така, ако транзакциите на клиента обхващат множество региони.

    Научени уроци

    Spendlytics е на живо от юли 2015 г. Оттогава ние наблюдаваме отблизо моделите на достъп и разглеждаме начини за оптимизиране на производителността. Искаме непрекъснато да подобряваме потребителското изживяване и да предоставяме на клиентите все по-голяма представа за разходите с карти. Останалата част от тази публикация описва уроците, които научихме от пускането на Spendlytics в производството и някои от оптимизациите, които бяха въведени.

    След първоначалното издание идентифицирахме редица болезнени точки, върху които искахме да се съсредоточим върху подобряването. Първият беше как да филтрирам резултатите по атрибут на транзакция. Както бе споменато по-рано, атрибутите на транзакциите са кодирани в записите на Avro, но открихме, че все по-голям брой модели на достъп искаха да филтрират по атрибут и потребителите бяха принудени да правят това от страна на клиента. Първоначалното решение беше да се внедри персонализиран HBase ValueFilter който приема нашите собствени сложни филтърни изрази, например:

    category='SUPERMARKETS' AND amount > 100 AND 
    (brand LIKE 'foo%' OR brand = 'bar')

    Изразът се оценява за всеки запис на Avro, което ни позволява да филтрираме резултатите от страна на сървъра и да намалим количеството данни, които се връщат на клиента (спестяване на мрежова честотна лента и обработка от страна на клиента). Филтърът влияе върху производителността на сканиране, но времето за реакция остава в рамките на целта от 200 мс.

    Това се оказа временно решение поради допълнителни промени, които бяха необходими за оптимизиране на записите. Поради начина, по който работи процеса на сетълмент с кредитни карти, първо получаваме упълномощен транзакция от момента на продажбата (в почти реално време) и след това известно време по-късно уредено транзакция от мрежата на кредитни карти (в пакет). Тези транзакции трябва да бъдат съгласувани, по същество чрез сливане на уредените транзакции с оторизирани транзакции, които вече са в HBase, присъединявайки се по ID на транзакцията. Като част от този процес атрибутите на транзакциите могат да се променят и да се добавят нови атрибути. Това се оказа болезнено поради режийните разходи за пренаписване на цели Avro записи - дори при актуализиране на отделни атрибути. Така че, за да направим атрибутите по-достъпни за актуализации, ги организирахме в колони, заменяйки сериализацията Avro.

    Ние също се интересуваме само от атомарността на ниво транзакция, така че разделянето на транзакциите по час не ни даде никакво предимство. Освен това, уредените транзакциите, които сега пристигат в пакет, имат детайлност само на ниво ден, което затруднява (скъпо) тяхното съгласуване със съществуващите упълномощени транзакции, съхранявани по часове. За да разрешим този проблем, преместихме идентификатора на транзакцията в rowkey и намалихме зърното на времевия клей на дни, а не на часове. Процесът на съгласуване вече е много по-лесен, защото можем просто да заредим групово промените в HBase и да оставим уреждането стойностите имат предимство.

    В обобщение:

    • Копроцесорите на Observer могат да бъдат ценен инструмент, но ги използвайте разумно.
    • За някои случаи на употреба разширяването на HBase API чрез крайни точки е добра алтернатива.
    • Използвайте персонализирани филтри, за да подобрите производителността чрез подрязване на резултатите от страната на сървъра.
    • Сериализираните стойности имат смисъл за правилния случай на употреба, но се възползват от силните страни на HBase, като предпочитат естествена поддръжка за полета и колони.
    • Управлението на предварително изчислени резултати е трудно; допълнителната латентност от изчисления в движение може да си струва.
    • Моделите за достъп ще се променят, така че бъдете пъргави и отворени за промени в схемата на HBase, за да се адаптирате и да останете пред играта.

    Пътна карта

    Оптимизация, която в момента оценяваме, са хибридните копроцесори. Това, което имаме предвид под това, е комбинацията от копроцесори на наблюдател и крайна точка за предварително изчисление на тенденциите. Въпреки това, за разлика от преди, ние не бихме направили това по пътя на запис, а във фонов режим, като се включим в операциите за изчистване и уплътняване на HBase. Наблюдател ще изчисли тенденциите по време на събития за изплакване и уплътняване въз основа на уреденото транзакции, налични към този момент. След това ще използваме крайна точка, за да комбинираме предварително изчислените тенденции с агрегации в движение на делтата на транзакциите. Чрез предварително изчисление на тенденциите по този начин се надяваме да дадем тласък на производителността при четене, без да се отразява на производителността на запис.

    Друг подход, който оценяваме за агрегиране на тенденциите и за достъп до HBase като цяло, е Apache Phoenix. Phoenix е SQL скин за HBase, който позволява достъп с помощта на стандартни JDBC API. Надяваме се, че с помощта на SQL и JDBC това ще опрости достъпа до HBase и ще намали количеството код, който трябва да напишем. Можем също така да използваме интелигентните модели на изпълнение на Phoenix и вградените копроцесори и филтри за бързо агрегиране. Phoenix се смяташе за твърде незрял за производствена употреба в началото на Spendlytics, но с подобни случаи на употреба, докладвани от като eBay и Salesforce, сега е моментът за преоценка. (Пакет Phoenix за CDH е наличен за инсталиране и оценка, но без поддръжка, чрез Cloudera Labs.)

    Santander наскоро обяви, че е първата банка, която пуска технология за гласово банкиране, която позволява на клиентите да говорят с приложението SmartBank и да питат за разходите по картата си. Платформата зад тази технология е Cloudera, а архитектурата за Spendlytics — както е описана в този набор от публикации — послужи като дизайн на чертежа.

    Джеймс Кинли е главен архитект за решения в Cloudera.

    Иън Бъс е старши архитект за решения в Cloudera.

    Педро Боадо е инженер на Hadoop в Сантандер (Исбан) Обединеното кралство.

    Абел Фернандес Алфонсо е инженер на Hadoop в Сантандер (Исбан) UK.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. HBase производителност CDH5 (HBase1) срещу CDH6 (HBase2)

  2. Как да:Тествайте HBase приложения с помощта на популярни инструменти

  3. Тестване на производителността на HBase с помощта на YCSB

  4. Cloudera Replication Plugin позволява репликация на x-платформа за Apache HBase

  5. Как HBase в CDP може да използва S3 на Amazon