Беш студент жана үч негизги баалуу дүкөндөр бөлүштүрүлгөн

Же ZooKeeper, etcd жана Consul KV үчүн C++ кардар китепканасын кантип жаздык

Бөлүштүрүлгөн системалар дүйнөсүндө бир катар типтүү милдеттер бар: кластердин курамы жөнүндө маалыматты сактоо, түйүндөрдүн конфигурациясын башкаруу, бузулган түйүндөрдү табуу, лидерди тандоо жана башкалар. Бул көйгөйлөрдү чечүү үчүн атайын бөлүштүрүлгөн системалар – координациялык кызматтар түзүлдү. Эми биз алардын үчөөнө кызыгабыз: ZooKeeper, etcd жана Consul. Консулдун бардык бай функцияларынын ичинен биз Консул К.В.

Беш студент жана үч негизги баалуу дүкөндөр бөлүштүрүлгөн

Чындыгында, бул системалардын баары катага чыдамдуу, сызыктуу ачкыч-нарк кампалары. Алардын маалымат моделдери олуттуу айырмачылыктарга ээ болсо да, биз кийинчерээк талкуулайбыз, алар ошол эле практикалык маселелерди чечет. Албетте, координациялык кызматты колдонгон ар бир тиркеме алардын бирине байланган, бул ар кандай тиркемелер үчүн бирдей маселелерди чечүүчү бир маалымат борборунда бир нече системаны колдоо зарылдыгына алып келиши мүмкүн.

Бул көйгөйдү чечүү идеясы австралиялык консалтингдик агенттикте пайда болгон жана аны ишке ашыруу бизге, студенттердин чакан командасына жүктөлгөн, мен бул тууралуу сөз кылам.

Биз ZooKeeper, etcd жана Consul KV менен иштөө үчүн жалпы интерфейсти камсыз кылган китепкана түзө алдык. Китепкана C++ тилинде жазылган, бирок аны башка тилдерге өткөрүү пландары бар.

Маалымат моделдери

Үч башка система үчүн жалпы интерфейсти иштеп чыгуу үчүн, алардын эмнеси менен жалпылыгын жана алар кандайча айырмаланарын түшүнүшүңүз керек. Келгиле, аны аныктап көрөлү.

ZooKeeper

Беш студент жана үч негизги баалуу дүкөндөр бөлүштүрүлгөн

Ачкычтар даракка уюшулган жана түйүндөр деп аталат. Демек, түйүн үчүн анын балдарынын тизмесин ала аласыз. Znode түзүү (түзүү) жана маанини өзгөртүү (setData) операциялары бөлүнгөн: учурдагы баскычтарды гана окууга жана өзгөртүүгө болот. Сааттар түйүндүн бар экендигин текшерүү, маанини окуу жана балдарды алуу операцияларына тиркелиши мүмкүн. Watch – сервердеги тиешелүү маалыматтардын версиясы өзгөргөндө күйүүчү бир жолку триггер. Эфемердик түйүндөр каталарды аныктоо үчүн колдонулат. Алар аларды жараткан кардардын сессиясына байланган. Кардар сеансты жапканда же ZooKeeperге анын бар экендиги жөнүндө кабарлоону токтоткондо, бул түйүндөр автоматтык түрдө жок кылынат. Жөнөкөй транзакциялар колдоого алынат - бул алардын жок дегенде бирөө үчүн мүмкүн болбосо, бардыгы ийгиликтүү же ийгиликсиз болгон операциялардын жыйындысы.

ж.б.

Беш студент жана үч негизги баалуу дүкөндөр бөлүштүрүлгөн

Бул системаны иштеп чыгуучулар ZooKeeperден шыктандырышкан, ошондуктан бардыгын башкача кылышкан. Ачкычтардын иерархиясы жок, бирок алар лексикографиялык иреттелген топтомду түзөт. Белгилүү бир диапазонго тиешелүү бардык баскычтарды алып же жок кыла аласыз. Бул структура кызыктай сезилиши мүмкүн, бирок ал чындыгында абдан экспрессивдүү жана иерархиялык көз карашты оңой эле туурап алса болот.

etcd стандарттык салыштыруу жана орнотуу операциясы жок, бирок анын жакшыраак нерсеси бар: транзакциялар. Албетте, алар бардык үч системада бар, бирок etcd транзакциялары өзгөчө жакшы. Алар үч блоктон турат: текшерүү, ийгилик, ийгиликсиздик. Биринчи блок шарттардын жыйындысын камтыйт, экинчи жана үчүнчү - операциялар. Транзакция атомдук түрдө ишке ашырылат. Эгерде бардык шарттар чын болсо, анда ийгилик блогу аткарылат, антпесе ийгиликсиз блок аткарылат. API 3.3, ийгилик жана ийгиликсиз блоктор уя транзакцияларды камтышы мүмкүн. Башкача айтканда, дээрлик ыктыярдуу уя деңгээлиндеги шарттуу конструкцияларды атомдук түрдө аткарууга болот. Сиз кайсы текшерүүлөр жана операциялар бар экендиги жөнүндө көбүрөөк биле аласыз документтер.

Бул жерде да сааттар бар, бирок алар бир аз татаалыраак жана кайра колдонууга болот. Башкача айтканда, саатты ачкыч диапазонуна орноткондон кийин, сиз биринчисин эле эмес, саатты жокко чыгарганга чейин бул диапазондогу бардык жаңыртууларды аласыз. ж.б., ZooKeeper кардар сессияларынын аналогу ижара болуп саналат.

Консул К.В.

Бул жерде да катуу иерархиялык структура жок, бирок Консул ал бар көрүнүштү түзө алат: көрсөтүлгөн префикс менен бардык ачкычтарды алып, жок кыла аласыз, башкача айтканда, ачкычтын "под дарагы" менен иштей аласыз. Мындай суроолор рекурсивдүү деп аталат. Мындан тышкары, консул префикстен кийин көрсөтүлгөн символду камтыбаган баскычтарды гана тандай алат, бул дароо "балдарды" алууга туура келет. Бирок, бул так иерархиялык структуранын көрүнүшү экенин эстен чыгарбоо керек: эгерде анын ата-энеси жок болсо, ачкычты түзүүгө же балдары бар ачкычты жок кылууга толук мүмкүн, ал эми балдар системада сакталып кала берет.

Беш студент жана үч негизги баалуу дүкөндөр бөлүштүрүлгөн
Сааттардын ордуна Консул HTTP сурамдарын бөгөттөп койду. Негизи булар башка параметрлер менен бирге маалыматтардын акыркы белгилүү версиясы көрсөтүлгөн маалыматтарды окуу ыкмасына кадимки чалуулар. Эгерде сервердеги тиешелүү маалыматтардын учурдагы версиясы көрсөтүлгөндөн чоңураак болсо, жооп дароо кайтарылат, антпесе - маани өзгөргөндө. Каалаган убакта ачкычтарга тиркелүүчү сессиялар да бар. Белгилей кетчү нерсе, etcd жана ZooKeeperден айырмаланып, сеанстарды жок кылуу байланышкан ачкычтарды жок кылууга алып келет, сеанс алардан жөн эле ажыратылган режим бар. жеткиликтүү бүтүмдөр, бутактары жок, бирок ар кандай чектер менен.

Баарын чогултуу

ZooKeeper эң катаал маалымат моделине ээ. etcd ичинде жеткиликтүү экспрессивдүү диапазон сурамдарын ZooKeeper же Консулда эффективдүү эмуляциялоо мүмкүн эмес. Бардык кызматтардын эң жакшысын кошууга аракет кылып, биз ZooKeeper интерфейсине дээрлик эквиваленттүү интерфейске ээ болдук жана төмөнкү олуттуу өзгөчөлүктөр менен:

  • ырааттуулугу, контейнер жана TTL түйүндөрү колдоого алынбайт
  • ACL колдоого алынбайт
  • коюлган ыкма ачкычты түзөт, эгерде ал жок болсо (ZK setData бул учурда катаны кайтарат)
  • set жана cas ыкмалары бөлүнөт (ZKде алар негизинен бир эле нерсе)
  • өчүрүү ыкмасы түйүндү анын ички дарагы менен бирге жок кылат (ZK тилинде өчүрүү түйүнүн балдары болсо, катаны кайтарат)
  • Ар бир ачкыч үчүн бир гана версия бар - баалуу версия (ZK алардын үчөө бар)

Ырааттуу түйүндөрдөн баш тартуу, etcd жана Consulда аларды колдобогондугу менен шартталган жана аларды колдонуучу пайда болгон китепкана интерфейсинин үстүнө оңой эле ишке ашыра алат.

Чокуну жок кылууда ZooKeeperге окшош жүрүм-турумду ишке ашыруу, etcd жана Consul ичиндеги ар бир ачкыч үчүн өзүнчө бала эсептегичти сактоону талап кылат. Мета-маалыматтарды сактоодон качууга аракет кылгандыктан, бүт ички даракты жок кылуу чечими кабыл алынды.

Ишке ашыруунун кылдат жактары

Ар кандай системаларда китепкана интерфейсин ишке ашыруунун кээ бир аспектилерин кененирээк карап чыгалы.

Иерархия ж.б

etcd ичинде иерархиялык көз карашты сактоо эң кызыктуу милдеттердин бири болуп чыкты. Диапазондун сурамдары көрсөтүлгөн префикси бар баскычтардын тизмесин алууну жеңилдетет. Мисалы, сиз менен башталган бардык нерсе керек болсо "/foo", сиз диапазонду сурап жатасыз ["/foo", "/fop"). Бирок бул ачкычтын бардык ички дарагын кайтарып берет, эгерде поддарак чоң болсо, бул туура эмес болушу мүмкүн. Алгач биз котормо механизмин колдонууну пландаштырганбыз. zetcd ишке ашырылган. Ал ачкычтын башына дарактын түйүнүнүн тереңдигине барабар бир байтты кошууну камтыйт. Мен бир мисал келтирейин.

"/foo" -> "u01/foo"
"/foo/bar" -> "u02/foo/bar"

Андан кийин ачкычтын бардык дароо балдарды алуу "/foo" диапазонун суроо менен мүмкүн ["u02/foo/", "u02/foo0"). Ооба, ASCIIде "0" дароо кийин турат "/".

Бирок, бул учурда бир чокусун алып салуу кантип ишке ашыруу керек? Көрсө, сиз түрдөгү бардык диапазондорду жок кылышыңыз керек ["uXX/foo/", "uXX/foo0") XX үчүн 01ден FFге чейин. Анан чуркап калдык операция номеринин чеги бир транзакциянын ичинде.

Натыйжада, ачкычты өчүрүүнү да, балдардын тизмесин алууну да эффективдүү ишке ашырууга мүмкүндүк берген жөнөкөй ачкычты конверсиялоо системасы ойлоп табылган. Акыркы белгинин алдында атайын белги кошуу жетиштүү. Мисалы:

"/very" -> "/u00very"
"/very/long" -> "/very/u00long"
"/very/long/path" -> "/very/long/u00path"

Андан кийин ачкычты жок кылуу "/very" жок кылууга айланат "/u00very" жана диапазон ["/very/", "/very0"), жана бардык балдарды алуу - диапазондогу ачкычтарды суроодо ["/very/u00", "/very/u01").

ZooKeeperдеги ачкычты алып салуу

Жогоруда айтылгандай, ZooKeeperде сиз түйүндөрдүн балдары бар болсо, аны жок кыла албайсыз. Биз ачкычты ички дарак менен бирге жок кылгыбыз келет. Мен эмне кылышым керек? Биз муну оптимизм менен жасайбыз. Биринчиден, биз ар бир чокунун балдарын өзүнчө суроо менен алып, ички даракты рекурсивдүү айланып чыгабыз. Андан кийин биз туура тартипте поддарактын бардык түйүндөрүн жок кылууга аракет кылган транзакцияны курабыз. Албетте, кошумча даракты окуу менен аны жок кылуунун ортосунда өзгөрүүлөр болушу мүмкүн. Бул учурда, транзакция ишке ашпай калат. Мындан тышкары, окуу процессинде субтрее өзгөрүшү мүмкүн. Кийинки түйүндүн балдарына суроо-талап катаны кайтарышы мүмкүн, эгерде, мисалы, бул түйүн мурда эле жок кылынса. Эки учурда тең процессти кайра кайталайбыз.

Бул ыкма ачкычты жок кылууну, эгерде анын балдары бар болсо, өтө натыйжасыз кылат, ал тургай, эгер тиркеме ички дарак менен иштей берсе, ачкычтарды жок кылып жана түзсө. Бирок, бул бизге etcd жана Консул башка ыкмаларын ишке ашырууну кыйындатуудан качууга мүмкүндүк берди.

ZooKeeperде орнотулган

ZooKeeperде дарак түзүмү менен иштеген (түзүү, өчүрүү, getChildren) жана түйүндөрдөгү маалыматтар менен иштеген (setData, getData) өзүнчө методдор бар. Мындан тышкары, бардык ыкмалардын катуу алдын ала шарттары бар: эгер түйүн мурунтан эле бар болсо, түзүү катаны кайтарат түзүлгөн, жок кылуу же setData – эгерде ал мурда жок болсо. Бизге ачкычтын бар-жоктугу жөнүндө ойлонбостон чакыра турган белгиленген ыкма керек болчу.

Бир вариант жок кылуу сыяктуу оптимисттик мамиле кылуу. Түйүн бар же жок экенин текшериңиз. Эгер бар болсо, setDataга чалыңыз, болбосо түзүңүз. Эгерде акыркы ыкма катаны кайтарса, аны кайра кайталаңыз. Белгилей кетчү нерсе, бар болуу сынагынын мааниси жок. Сиз дароо түзүү чакыра аласыз. Ийгиликтүү бүтүрүү түйүн болгон эмес жана ал түзүлгөн дегенди билдирет. Болбосо, түзүү тиешелүү катаны кайтарат, андан кийин setDataга чалышыңыз керек. Албетте, чалуулардын ортосунда бир чоку атаандаш чакыруу менен жок кылынышы мүмкүн жана setData да катаны кайтарып берет. Бул учурда, сиз баарын кайра жасай аласыз, бирок бул татыктуубу?

Эгерде эки ыкма тең катаны кайтарса, анда атаандаштык жок кылуу болгонун так билебиз. Бул өчүрүү set чакыргандан кийин болду деп элестетип көрөлү. Анда биз орнотууга аракет кылып жаткан кандай гана маани болбосун, эчак эле өчүрүлгөн. Бул, чынында, эч нерсе жазылбаса да, топтом ийгиликтүү аткарылды деп болжолдоого болот дегенди билдирет.

Көбүрөөк техникалык маалымат

Бул бөлүмдө биз бөлүштүрүлгөн системалардан тыныгуу алып, коддоо жөнүндө сүйлөшөбүз.
Кардардын негизги талаптарынын бири кросс-платформа болгон: кызматтардын жок дегенде бири Linux, MacOS жана Windows системаларында колдоого алынышы керек. Башында биз Linux үчүн гана иштеп чыктык, кийинчерээк башка системаларда сынай баштадык. Бул бир нече убакытка чейин кандай мамиле кылуу керектиги такыр белгисиз болгон көптөгөн көйгөйлөрдү жаратты. Натыйжада, бардык үч координациялоо кызматтары азыр Linux жана MacOS'та колдоого алынат, ал эми Windows'до Consul KV гана колдоого алынат.

Кызматтарга кирүү үчүн биз башынан эле даяр китепканаларды колдонууга аракет кылдык. ZooKeeper учурда тандоо туура келди ZooKeeper C++, акыры Windows'до компиляция кыла алган жок. Бирок, бул таң калыштуу эмес: китепкана Linux үчүн гана жайгашкан. Консул үчүн жалгыз вариант болчу ppconsul. Ага колдоо кошуу керек болчу сессиялар и транзакциялар. etcd үчүн, протоколдун акыркы версиясын колдогон толук кандуу китепкана табылган жок, ошондуктан биз жөн гана grpc кардары түзүлгөн.

ZooKeeper C++ китепканасынын асинхрондук интерфейсинен шыктанып, биз асинхрондук интерфейсти да ишке ашырууну чечтик. ZooKeeper C++ бул үчүн келечектеги/промите примитивдерин колдонот. STLде, тилекке каршы, алар өтө жөнөкөй ишке ашырылат. Мисалы, жок андан кийин ыкма, ал берилген функцияны келечектеги натыйжа жеткиликтүү болгондо колдонот. Биздин учурда мындай ыкма натыйжаны биздин китепкананын форматына айландыруу үчүн зарыл. Бул көйгөйдү чечүү үчүн биз өзүбүздүн жөнөкөй жип пулубузду ишке ашырышыбыз керек болчу, анткени кардардын талабы боюнча биз Boost сыяктуу үчүнчү тараптын оор китепканаларын колдоно албадык.

Биздин андан кийин ишке ашыруу ушундай иштейт. Чакырганда, кошумча убада/келечектеги жуп түзүлөт. Жаңы келечек кайтарылып берилет, ал эми өтүп кеткени тиешелүү функция жана кошумча убада менен катар кезекке коюлат. Бассейндеги жип кезектен бир нече фьючерстерди тандап, wait_for аркылуу сурамжылоо жүргүзөт. Натыйжа жеткиликтүү болгондо, тиешелүү функция чакырылат жана анын кайтаруу мааниси убадага өтөт.

Биз etcd жана консулга суроо-талаптарды аткаруу үчүн ошол эле жип пулун колдондук. Бул негизги китепканаларга бир нече ар кандай жиптер аркылуу кирүүгө болот дегенди билдирет. ppconsul жип коопсуз эмес, андыктан ага чалуулар кулпулар менен корголот.
Сиз бир нече жиптен grpc менен иштей аласыз, бирок майда-барат жактары бар. etcd сааттары grpc агымдары аркылуу ишке ашырылат. Бул белгилүү бир типтеги билдирүүлөр үчүн эки багыттуу каналдар. Китепкана бардык сааттар үчүн бир жипти жана келген билдирүүлөрдү иштеткен бир жипти түзөт. Ошентип, grpc агымга параллелдүү жазууга тыюу салат. Бул саатты инициализациялоодо же жок кылууда, кийинкисин жөнөтүүдөн мурун мурунку сурам жөнөтүлүп бүткүчө күтүшүңүз керек дегенди билдирет. Биз синхрондоштуруу үчүн колдонобуз шарттуу өзгөрмөлөр.

жыйынтык

Сен үчүн карагыла: liboffkv.

Биздин команда: Раед Романов, Иван Глушенков, Дмитрий Камалдинов, Виктор Крапивенский, Виталий Иванин.

Source: www.habr.com

Комментарий кошуу