У дакладзе Андрэй Барадзін раскажа, як яны ўлічылі вопыт маштабавання PgBouncer пры праектаванні пулера злучэнняў
Відэа:
Ўсім прывітанне! Мяне клічуць Андрэй.
У Яндэксе я займаюся распрацоўкай open source баз дадзеных. І сёньня ў нас тэма пра connection pooler злучэньняў.
Калі вы ведаеце, як назваць connection pooler па-руску, то скажыце мне. Я вельмі хачу знайсці добры тэхнічны тэрмін, які павінен устаяцца ў тэхнічнай літаратуры.
Тэма даволі складаная, таму што ў шматлікіх базах дадзеных connection pooler убудаваны і пра яго нават ведаць не трэба. Нейкія наладкі, вядома, усюды ёсць, але ў Postgres так не атрымліваецца. І паралельна (на HighLoad++ 2019) ідзе даклад Мікалая Самахвалава пра настройку запытаў у Postgres. І я так разумею, што сюды прыйшлі людзі, якія ўжо настроілі запыты ідэальна, і гэта людзі, якія сутыкаюцца з больш рэдкімі сістэмнымі праблемамі, звязанымі з сеткай, утылізацыяй рэсурсаў. І месцамі гэта можа было даволі складана ў тым плане, што праблемы невідавочныя.
У Яндэксе ёсць Postgres. У Яндекс.Облаке жывуць многія сэрвісы Яндекса. І ў нас некалькі петабайт дадзеных, якія генеруюць не менш за мільён запытаў у секунду ў Postgres.
І мы даем дастаткова тыпавы кластар усім сэрвісам – гэта асноўная primary нода вузла, звычайныя дзве рэплікі (сінхронная і асінхронная), рэзервовае капіраванне, маштабаванне чытаючых запытаў на рэпліцы.
Кожны вузел кластара - гэта Postgres, на якім акрамя Postgres і сістэм маніторынгу яшчэ ўсталяваны connection pooler. Connection pooler выкарыстоўваецца для fencing і па сваім асноўным прызначэнні.
Што такое асноўнае прызначэнне connection pooler?
У Postgres прынятая працэсная мадэль пры працы з базай дадзеных. Гэта азначае, што адно злучэнне - гэта адзін працэс, адзін бэкенд Postgres. І ў гэтым бэкендзе вельмі шмат розных кэшаў, якія даволі дорага рабіць рознымі для розных злучэнняў.
Акрамя таго, у кодзе Postgres ёсць масіў, які завецца procArray. Ён змяшчае асноўныя дадзеныя аб сеткавых злучэннях. І амаль усе алгарытмы апрацоўкі procArray маюць лінейную складанасць, яны прабягаюцца па ўсім масіве сеткавых злучэнняў. Гэта даволі хуткі цыкл, але з вялікай колькасцю ўваходзяць сеткавых злучэнняў усё становіцца крыху даражэй. А калі ўсё стала крыху даражэй, у выніку можна заплаціць вельмі вялікі кошт за вялікую колькасць сеткавых злучэнняў.
Існуюць 3 магчымыя падыходы:
- На баку прыкладання.
- На баку базы дадзеных.
- І паміж, т. е. разнастайныя камбінацыі.
Нажаль, убудаваны pooler цяпер знаходзіцца ў стадыі распрацоўкі. Сябры ў кампаніі PostgreSQL Professional у асноўным гэтым займаюцца. Калі ён з'явіцца, цяжка прадказаць. І фактычна на выбар архітэктара ў нас два рашэнні. Гэта application-side pool і proxy pool.
Application-side pool - гэта самы просты спосаб. І амаль усе кліенцкія драйвера вам падаюць спосаб: мільёны вашых злучэнняў у кодзе прадставіць у выглядзе некаторых дзясяткаў злучэнняў у базу дадзеных.
Узнікае праблема з тым, што ў пэўны момант вы хочаце маштабаваць бэкэнд, вы хочаце разгарнуць яго на мноства віртуальных машын.
Затым вы яшчэ разумееце, што ў вас яшчэ некалькі зон даступнасцяў, некалькі дата-цэнтраў. І падыход з client side pooling прыводзіць да вялікіх лікаў. Вялікія - гэта каля 10 000 злучэнняў. Гэта край, што можа нармальна працаваць.
Калі казаць пра proxy poolers, то ёсць два poolers, якія ўмеюць шмат усяго. Яны не толькі poolers. Яны poolers + яшчэ класная функцыянальнасць. Гэта
Але, нажаль, гэтая дадатковая функцыянальнасць не ўсім патрэбна. І яна прыводзіць да таго, што poolers падтрымліваюць толькі сесійны pooling, т. е. адзін уваходны кліент, адзін выходны кліент у базу дадзеных.
Для нашых задач гэта не вельмі добрае падыходзіць, таму мы выкарыстоўваем PgBouncer, які рэалізуе transaction pooling, т. е. серверныя злучэнні супастаўляюцца кліенцкім злучэнням толькі на час транзакцыі.
І на нашай нагрузцы - гэта праўда. Але ёсць некалькі праблем.
Праблемы пачынаюцца, калі вы хочаце дыягнаставаць сесію, таму што ўсе ўваходныя злучэнні ў вас лакальныя. Усе дашлі з loopback і неяк трасаваць сесію становіцца складана.
Вядома, вы можаце выкарыстоўваць application_name_add_host. Гэта спосаб на баку Bouncer дадаць IP-адрас у application_name. Але application_name усталёўваецца дадатковым злучэннем.
На гэтым графіку, дзе жоўтая лінія - гэта рэальныя запыты, а дзе сіняя - запыты, якія ўлятаюць у базу. І вось гэтая розніца - гэта менавіта ўсталёўка application_name, які патрэбен толькі для трасіроўкі, але ён зусім не бясплатны.
Акрамя таго, у Bouncer нельга абмежаваць адзін pool, т. е. колькасць злучэнняў з базай дадзеных на вызначанага карыстача, на вызначаную базу.
Да чаго гэта прыводзіць? У вас ёсць нагружаны сэрвіс, напісаны на C++ і дзесьці побач маленькі сэрвіс на нодзе, які нічога страшнага з базай не робіць, але яго драйвер вар'яцее. Ён адчыняе 20 000 злучэнняў, а ўсё астатняе пачакае. У вас нават код нармальны.
Мы, вядома, напісалі маленькі патч для Bouncer, які дадаў гэтую настройку, г. зн. абмежаванне кліентаў на pool.
Можна было б гэта зрабіць на баку Postgres, т. е. ролі ў базе дадзеных абмежаваць колькасцю злучэнняў.
Але тады вы страціце магчымасць зразумець, чаму ў вас няма злучэнняў з серверам. PgBouncer не прабівае памылку злучэння, ён вяртае заўсёды адну і тую ж інфармацыю. І вы не можаце зразумець: магчыма, у вас пароль памяняўся, магчыма, проста база лягла, магчыма, нешта не так. Але дыягностыкі ніякай няма. Калі сесію нельга ўсталяваць, вы не даведаецеся, чаму гэта нельга зрабіць.
У пэўны момант вы глядзіце на графікі дадатку і бачыце, што прыкладанне не працуе.
Глядзіце ў топ і бачыце, што Bouncer аднаструменны. Гэта паваротны момант у жыцці сервісу. Вы разумееце, што вы рыхтаваліся да маштабавання базы дадзеных праз паўтара гады, а вам трэба маштабаваць pooler.
Мы прыйшлі да таго, што нам трэба больш PgBouncer'аў.
Трохі запатчылі Bouncer.
І зрабілі так, што могуць быць паднятыя з перавыкарыстаннем TCP-порта некалькі Bouncers. І ўжо аперацыйная сістэма ўваходныя TCP-злучэнні паміж імі аўтаматычна round-robin'ом перакладае.
Гэта празрыста для кліентаў, т. е. усё выглядае так, як быццам у вас адзін Bouncer, але ў вас ёсць фрагментацыя idle-злучэнняў паміж запушчанымі Bouncer'амі.
І ў пэўны момант вы можаце заўважыць, што вось гэтыя 3 Bouncers з'ядаюць кожны сваё ядро на 100%. Вам трэба шмат Bouncers. Чаму?
Таму што ў вас есць TLS. У вас ёсць шыфраванае злучэнне. І калі пробенчмаркаць Postgres з TLS і без TLS, тыя вы выявіце, што колькасць усталяваных злучэнняў падае амаль на два парадку з уключэннем шыфравання, таму што TLS handshake спажывае рэсурсы цэнтральнага працэсара.
І ў топе вы можаце ўбачыць даволі шмат крыптаграфічных функцый, якія выконваюцца пры хвалі ўваходзяць злучэнняў. Паколькі ў нас primary можа перамыкацца паміж зонамі даступнасці, то хваля ўваходзячых злучэнняў - гэта даволі тыповая сітуацыя. Т. е. па нейкай прычыне стары primary быў недаступны, усю нагрузку адправілі ў іншы дата-цэнтр. Яны ўсе адначасова прыйдуць павітацца з TLS.
І вялікая колькасць TLS handshake можа не вітацца ўжо з Bouncer, а горла яму здушыць. З-за таймаўту хваля ўваходных злучэнняў можа стаць незатухаючай. Калі ў вас retry у базу без exponential backoff, яны не будуць прыходзяць зноў і зноў кагерэнтнай хваляй.
Вось прыклад 16 PgBouncer, якія грузяць 16 ядраў на 100%.
Мы дашлі да каскаднага PgBouncer. Гэта найлепшая канфігурацыя, якую можна дасягнуць на нашай нагрузцы з Bouncer. Вонкавыя Bouncers у нас служаць для TCP handshake, а ўнутраныя Bouncers служаць для рэальнага pooling, для таго, каб не моцна фрагментаваць вонкавыя злучэнні.
У такой канфігурацыі магчымы плыўны рэстарт. Можна рэстартаваць ўсе гэтыя 18 Bouncers па адным. Але падтрымліваць такую канфігурацыю дастаткова складана. Сістэмныя адміністратары, DevOps і людзі, якія сапраўды нясуць адказнасць за гэты сервер, будуць не вельмі рады такой схеме.
Здавалася б, можна ўсе нашы дапрацоўкі прасоўваць у open source, але Bouncer не вельмі добрае сапсуецца. Напрыклад, магчымасць, запусціць некалькі PgBouncers на адным порце закамміцілі месяц таму. А pull request з гэтай функцыяй быў некалькі год таму.
Або яшчэ адзін прыклад. У Postgres вы можаце адмяніць які выконваецца запыт, адправіўшы сакрэт па-іншаму злучэнню без лішняй аўтэнтыфікацыі. Але некаторыя кліенты адпраўляюць проста TCP-reset, т. е. ірвуць сеткавае злучэнне. Што пры гэтым зробіць Bouncer? Ён нічога не зробіць. Ён працягне выконваць запыт. Калі ў вас прыйшло мноства злучэнняў, якія невялікімі запытамі паклалі аснову, то лёгка адарваць злучэнне ад Bouncer будзе недастаткова, неабходна яшчэ завяршыць тыя запыты, якія бягуць у базе.
Гэта было запатчана і гэтую праблему ўсё яшчэ не ўмяржылі ў upstream Bouncer'а.
І так мы дашлі да таго, што нам патрэбен свой connection pooler, які будзе развівацца, патчыцца, у якім можна будзе аператыўна выпраўляць праблемы і які, вядома, павінен быць шматструменным.
Шматструменнасць мы паставілі як асноўную задачу. Нам трэба добра вытрымліваць хвалю якія ўваходзяць TLS-злучэнняў.
Для гэтага нам прыйшлося распрацаваць асобную бібліятэку, якая завецца Machinarium, якая прызначаная для апісання машынных станаў сеткавага злучэння як паслядоўнага кода. Калі вы паглядзіце ў зыходны код libpq, то вы ўбачыце даволі складаныя выклікі, якія могуць вярнуць вам вынік і сказаць: «Выклічы мяне крыху пазней. Цяпер у мяне пакуль што IO, але, калі IO пройдзе ў мяне нагрузка для працэсара». І гэта шматузроўневая схема. Сеткавае ўзаемадзеянне звычайна апісваюць машынай станаў. Мноствам правілаў тыпу "Калі я раней атрымаў загаловак пакета памеру N, то зараз я чакаю N байт", "Калі я адпраўляў пакет SYNC, то зараз я чакаю пакет з метададзенымі выніку". Атрымліваецца даволі складаны контринтуитивный код, як калі б лабірынт пераўтварылі ў маленькую разгортку. Мы зрабілі так, што замест машыны станаў праграміст апісвае асноўны шлях узаемадзеяння ў выглядзе звычайнага імператыўнага кода. Проста ў гэтым імператыўным кодзе трэба ўстаўляць месцы, дзе паслядоўнасць выканання трэба перапыніць чаканнем дадзеных ад сеткі, перадаўшы кантэкст выканання іншай каруціне (green thread-у). Гэты падыход аналагічны таму, што мы самы чаканы шлях у лабірынце запісваем запар, а потым дадаем да яго адгалінавання.
У выніку ў нас ёсць адзін струмень, які робіць TCP accept і round-robin'ом перадае мноству workers TPC-злучэнне.
Пры гэтым кожнае кліенцкае злучэнне працуе заўсёды на адным працэсары. І гэта дазваляе зрабіць яго cache-friendly.
І акрамя таго, мы дапрацавалі крыху збор маленькіх пакетаў у адзін вялікі пакет для таго, каб разгрузіць сістэмны TCP-stack.
Акрамя таго, мы палепшылі транзакцыйны пулінг у тым плане, што Odyssey пры ўсталяванай наладзе можа адправіць CANCEL і ROLLBACK у выпадку абрыву сеткавага злучэння, т. е. калі запыт ніхто не чакае, Odyssey скажа базе, каб яна не імкнулася выканаць той запыт, які можа расходаваць каштоўныя рэсурсы.
І па магчымасці мы захоўваем злучэнні за адным і тым жа кліентам. Гэта дазваляе не пераўсталёўваць application_name_add_host. Калі гэта магчыма, то ў нас няма дадатковай пераўсталёўкі параметраў, якія патрэбны для дыягностыкі.
Мы працуем у інтарэсах Яндэкс.Аблокі. І калі вы карыстаецеся managed PostgreSQL і ў вас усталяваны connection pooler, вы можаце стварыць лагічную рэплікацыю вонкі, т. е. з'ехаць ад нас, калі вам захочацца, пры дапамозе лагічнай рэплікацыі. Bouncer вонкі струмень лагічнай рэплікацыі не аддасць.
Гэта прыклад настройкі лагічнай рэплікацыі.
Акрамя таго, у нас ёсць падтрымка фізічнай рэплікацыі вонкі. У Воблаку яна, вядома, немагчымая, таму што тады вам кластар аддасць занадта шмат інфармацыі пра сябе. Але ў вашых усталёўках, калі вам патрэбна фізічная рэплікацыя праз connection pooler у Odyssey, гэта магчыма.
У Odyssey цалкам сумяшчальны маніторынг з PgBouncer. У нас такая ж кансоль, якая выконвае амаль усе тыя ж самыя каманды. Калі чагосьці бракуе, дасылайце pull request, ці хаця б issue у GitHub, будзем дарабляць патрэбныя каманды. Але асноўная функцыянальнасць кансолі PgBouncer у нас ужо ёсць.
І, канешне, у нас ёсць error forwarding. Мы вернем тую памылку, якую паведаміла база. Вы атрымаеце інфармацыю, чаму вы не пападаеце ў базу, а не проста, што вы ў яе не пападаеце.
Гэтая магчымасць выключаецца на выпадак, калі вам патрэбна 100%-ная сумяшчальнасць з PgBouncer. Мы можам паводзіць сябе гэтак жа, як Bouncer, проста на ўсялякі выпадак.
Распрацоўка
Некалькі слоў аб зыходным кодзе Odyssey.
Напрыклад, ёсць каманды "Pause / Resume". Яны звычайна выкарыстоўваюцца для абнаўлення базы дадзеных. Калі вам трэба абнавіць Postgres, тыя вы можаце паставіць яго на паўзу ў connection pooler, зрабіць pg_upgrade, пасля гэтага зрабіць resume. І са боку кліента гэта будзе выглядаць так, як быццам база проста тармазіла. Гэтую функцыянальнасць нам прынеслі людзі з супольнасці. Яна пакуль яшчэ не прымеркавана, але хутка ўсё будзе. (Ужо прымержана)
Акрамя таго, адна з новых фіч у PgBouncer, гэта падтрымка SCRAM Authentication, якую нам таксама прынёс чалавек, які не працуе ў Яндэкс.Аблокі. І тое і іншае - гэта складаная функцыянальнасць і важная.
Таму хочацца расказаць з чаго зроблены Odyssey, раптам вы таксама зараз хочаце крышку папісаць код.
У вас ёсць зыходная база Odyssey, якая абапіраецца на дзве асноўныя бібліятэкі. Бібліятэка Kiwi - гэта рэалізацыя Postgres'авага пратакола паведамленняў. Т. е. натыўны proto 3 у Postgres – гэта стандартныя паведамленні, якімі франтэнды, бэкенды могуць абменьвацца. Яны рэалізаваны ў бібліятэцы Kiwi.
Бібліятэка Machinarium - гэта бібліятэка рэалізацыі патокаў. Невялікі фрагмент гэтага Machinarium напісаны на асэмблеры. Але, не палохайцеся, тамака ўсяго 15 радкоў.
Архітэктура Odyssey. Ёсць асноўная машына, у якой запушчаны coroutines. У гэтай машыне рэалізуецца accept уваходных TCP-злучэнняў і размеркаванне па workers.
Унутры аднаго worker можа працаваць апрацоўшчык некалькіх кліентаў. А таксама галоўным чынам струмені круцяцца кансоль і апрацоўка crone-задач па выдаленні злучэнняў, якія больш не патрэбныя ў pool.
Для тэставання Odyssey выкарыстоўваецца стандартны набор тэстаў Postgres. Проста запускаем install-check праз Bouncer і праз Odyssey, атрымліваем нулявы div. Там некалькі тэстаў, звязаныя з фарматаваннем дат, не праходзяць абсалютна аднолькава ў Bouncer і ў Odyssey.
Акрамя таго, ёсць мноства драйвераў, якія маюць сваё тэсціраванне. І іх тэсты мы выкарыстоўваем для тэсціравання Odyssey.
Акрамя таго, з-за нашай каскаднай канфігурацыі нам даводзіцца тэставаць розныя звязкі: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey для таго, каб быць упэўненымі ў тым, што, калі Odyssey апынуўся ў нейкай з частак у каскадзе, ён таксама па-ранейшаму працуе так, як мы чакаем.
граблі
Мы выкарыстоўваем Odyssey у production. І было б не сумленна, калі б я сказаў, што ўсё проста працуе. Не, т. е. так, але не заўсёды. Напрыклад, у production усё проста працавала, потым дашлі нашы сябры з PostgreSQL Professional і сказалі, што ў нас ёсць memory leak. Яны праўда былі, мы іх выправілі. Але гэта было проста.
Потым мы выявілі, што ў connection pooler ёсць уваходныя TLS-злучэнні і выходныя TLS-злучэнні. І ў злучэннях патрэбны кліенцкія сертыфікаты і серверныя сертыфікаты.
Серверныя сертыфікаты Bouncer і Odyssey перачытваюць іх pcache, але кліенцкія сертыфікаты перачытваць з pcache не трэба, таму што наш які маштабуецца Odyssey у выніку ўпіраецца ў сістэмную прадукцыйнасць чытання гэтага сертыфіката. Гэта для нас стала нечаканасцю, таму што ўпёрся ён далёка не адразу. Спачатку ён лінейна маштабаваўся, а пасля 20 000 уваходных адначасовых злучэнняў гэтая праблема сябе выявіла.
Pluggable Authentication Method - гэта магчымасць аўтэнтыфікавацца ўбудаванымі lunux'авымі сродкамі. У PgBouncer яна рэалізавана так, што ёсць асобны струмень на чаканне адказу ад PAM і ёсць асноўны струмень PgBouncer, які абслугоўвае бягучае злучэнне і можа папытаць іх пажыць у струмені PAM.
Мы гэта не сталі рэалізоўваць па адной простай прычыне. У нас жа шмат плыняў. Навошта нам гэта патрэбна?
У выніку гэта можа ствараць праблемы з тым, што, калі ў вас ёсць PAM-аўтэнтыфікацыя і не PAM-аўтэнтыфікацыі, то вялікая хваля PAM-аўтэнтыфікацыі можа істотна затрымліваць не PAM-аўтэнтыфікацыю. Гэта адна з тых штук, якую мы не выправілі. Але калі вы хочаце гэта выправіць, можаце заняцца вось гэтым.
Яшчэ адны граблі былі з тым, што ў нас ёсць адзін паток, які робіць accept усім уваходным злучэнням. І потым іх перадае на worker pool, дзе будзе адбывацца TLS handshake.
У выніку, калі ў вас ёсць кагерэнтная хваля з 20 000 сеткавых злучэнняў, яны ўсё будуць прынятыя. І на баку кліента libpq пачне справаздачу таймаўтаў. Па змаўчанні накшталт 3 секунды тамака варта.
Калі яны ўсё не могуць адначасова зайсці ў базу, то яны не могуць зайсці ў базу, таму што ўсё гэта можа быць пакрыта не экспанентным retry.
Мы прыйшлі да таго, што скапіявалі тут схему з PgBouncer з тым, што ў нас есць throttling колькасці TCP-злучэнняў, якім мы робім accept.
Калі мы бачым, што мы аксепцім злучэнні, а яны ў выніку не паспяваюць пахендшайкіцца, мы ставім іх у чаргу для таго, каб яны не расходавалі рэсурсы цэнтральнага працэсара. Гэта прыводзіць да таго, што адначасовы handshake можа рабіцца не для ўсіх злучэнняў, якія прыйшлі. Але хаця б нехта ў базу зойдзе, нават калі нагрузка дастаткова моцная.
Дарожная карта
Чаго хацелася б убачыць у будучыні ў Odyssey? Што мы гатовы самі распрацоўваць і што мы чакаем ад супольнасці?
На жнівень 2019 года.
Вось так выглядаў roadmap Odyssey у жніўні:
- Мы хацелі SCRAM і PAM authentication.
- Мы хацелі forward якія чытаюць запытаў на standby.
- Жадалася бы online-restart.
- І магчымасць рабіць паўзу на сэрвэры.
Палова гэтага roadmap выканана, прычым не намі. І гэта добра. Таму давайце абмяркуем тое, што засталося і дадамо яшчэ.
У прынцыпе, у Postgres, пачынаючы з дзясяткі ёсць магчымасць пры злучэнні паказаць гэтак жа session_attrs. Вы ў злучэнні можаце пералічыць усе хасты баз дадзеных і сказаць, навошта вы ідзяце ў базу дадзеных: запісаць ці толькі прачытаць. І драйвер сам абярэ першы па спісе хост, які яму больш падабаецца, які выконвае патрабаванні session_attrs.
Але праблема гэтага падыходу ў тым, што ён не кантралюе лаг рэплікацыі. У вас можа быць нейкая рэпліка, якая адстала на непрымальны для вашага сервісу час. Для таго каб зрабіць поўнафункцыянальнае выкананне якія чытаюць запытаў на рэпліцы, у сутнасці, нам трэба падтрымаць у Odyssey магчымасць не працаваць, калі чытаць нельга.
Odyssey павінен хадзіць часам у базу і пытаць рэплікацыйную адлегласць ад primary. І калі яно дасягнула лімітавага значэння, новыя запыты ў базу не пускаць, сказаць кліенту, што трэба зноўку ініцыяваць злучэнні і, магчыма абраць іншы хост для выканання запытаў. Гэта дазволіць базе хутчэй аднавіць рэплікацыйны лаг і зноў вярнуцца для адказу запытам.
Тэрміны рэалізацыі складана назваць, бо гэта open source. Але, спадзяюся, што не 2,5 гады як у калегаў з PgBouncer. Вось гэтую функцыю хацелася б бачыць у Odyssey.
Але ёсць prepared statement на ўзроўні пратаколу паведамленняў на proto3. І гэта тое месца, калі інфармацыя аб тым, што ствараецца prepared statement, прыходзіць у структураваным выглядзе. І мы маглі б падтрымаць разуменне таго, што на нейкім сэрвэрным злучэнні кліент папрасіў стварыць prepared statements. І нават калі транзакцыя зачынілася, нам трэба па-ранейшаму падтрымліваць складнасць сервера і кліента.
Але тут узнікае разыходжанне ў дыялогу, таму што хтосьці кажа аб тым, што трэба разумець, які менавіта prepared statements стварыў кліент і падзяляць сервернае злучэнне паміж усімі кліентамі, якія стварылі гэтае сервернае злучэнне, т. е. якія стварылі такі prepared statement.
Андрэс Фройнд сказаў, што калі да вас прыйшоў кліент, які ўжо ствараў у іншым серверным злучэнні такі prepared statement, то стварыце яго за яго. Але, здаецца, гэта крыху няправільна выконваць запыты ў базе замест кліента, але з пункту гледжання распрацоўшчыка, які піша пратакол узаемадзеяння з базай, гэта было б зручна, калі б яму проста далі сеткавае злучэнне, у якім ёсць такі падрыхтаваны запыт.
І яшчэ адна фіча, якую нам трэба рэалізаваць. У нас зараз ёсць маніторынг, сумяшчальны з PgBouncer. Мы можам вярнуць сярэдні час выканання запыту. Але сярэдні час - гэта сярэдняя тэмпература па бальніцы: хтосьці халодны, хтосьці цёплы - у сярэднім усе здаровыя. Гэта не праўда.
Нам трэба рэалізаваць падтрымку перцэнтыляў, якія б указвалі на тое, што ёсць павольныя запыты, якія расходуюць рэсурсы, і зрабілі б маніторынг больш прымальным.
Самае галоўнае - жадаецца версію 1.0 (Ужо выйшла версія 1.1). Справа ў тым, што зараз Odyssey знаходзіцца ў версіі 1.0rc, т. е. release candidate. І ўсе граблі, якія я пералічыў, былі адрамантаваны роўна з той самай версіяй, акрамя memory leak.
Што для нас будзе азначаць вэрсія 1.0? Мы выкочваем Odyssey на свае базы. Ён ужо цяпер працуе на нашых базах, але калі ён дасягне кропкі ў 1 запытаў у секунду, то мы можам сказаць, што гэта рэлізная версія і гэта версія, якую можна назваць 000.
У суполцы некалькі чалавек папрасілі, каб у версіі 1.0 былі яшчэ паўза і SCRAM. Але гэта будзе азначаць, што нам трэба будзе выкаціць у production ужо наступную версію, таму што ні SCRAM, ні паўза да гэтага часу не змярцвелы. Але, хутчэй за ўсё, гэтае пытанне будзе дастаткова аператыўна вырашана.
Я чакаю вашых захапляльных патрабаванняў. І яшчэ хацелася б пачуць, якія ў вас есць праблемы з Bouncer. Давайце іх абмяркуем. Можа быць, мы зможам нейкія функцыі рэалізаваць, якія патрэбны вам.
На гэтым мая частка скончана, я хацеў бы паслухаць вас. Дзякуй!
пытанні
Калі я свой пастаўлю application_name, ён будзе правільна прачынацца, у тым ліку ў transaction pooling у Odyssey?
У Odyssey ці ў Bouncer?
У Odyssey. У Bouncer прачынаецца.
Сэт мы зробім.
І калі маё рэальнае злучэнне будзе скакаць па іншых злучэннях, то яно будзе перадавацца?
Мы зробім сэт усіх параметраў, якія пералічаны ў спісе. Я не магу сказаць, ці ёсць у гэтым спісе application_name. Здаецца, яго там бачыў. Мы ўсталюем усё тыя ж параметры. Адным запытам там сэт зробіць усё тое, што было ўсталявана кліентам пры стартапе.
Дзякуй, Андрэй, за даклад! Добры даклад! Рады, што Odyssey з кожнай хвілінай развіваецца ўсё хутчэй і хутчэй. Жадаю гэтак жа працягваць. Мы ўжо да вас звярталіся з просьбай мець multi data-source падлучэнне, каб Odyssey мог падлучацца адначасова да розных баз дадзеных, т. е. майстар slave, а потым аўтаматычна пасля failover падлучацца да новага майстра.
Так, я, здаецца, узгадваю гэтую дыскусію. Цяпер ёсць некалькі storages. Але пераключэння паміж імі няма. Мы павінны на сваім баку апытваць сэрвер, што ён яшчэ жывы і разумець, што адбыўся failover, хто выкліча pg_recovery. У мяне ёсць стандартны спосаб зразумець, што мы дашлі не на майстар. І мы павінны зразумець неяк з памылак ці як? Т. е. ідэя цікавая, яна абмяркоўваецца. Пішыце больш каментароў. Калі ў вас ёсць працоўныя рукі, якія ведаюць C, тое гэта наогул выдатна.
Пытанне маштабавання па рэпліках нас таксама цікавіць, таму што мы хочам зрабіць adoption рэплікаваных кластараў максімальна простым для распрацоўшчыкаў дадатку. Але тут жадалася б больш каментароў, т. е. як менавіта зрабіць, як добра зрабіць.
Пытанне таксама пра рэплікі. Атрымліваецца, што ў вас ёсць майстар і некалькі рэплікаў. І зразумела, што ў рэпліку ходзяць радзей, чым у майстар за злучэннямі, бо ў іх можа быць адрозненне. Вы казалі, што адрозненне ў дадзеных можа быць такое, што не будзе задавальняць ваш бізнэс і вы не будзеце туды хадзіць, пакуль яна не дарэплікуецца. Пры гэтым калі вы доўга туды не хадзілі, а потым пачалі хадзіць, то тыя дадзеныя, якія патрэбныя, не будуць адразу даступныя. Т. е. калі мы ўвесь час ходзім у майстар, то там кэш прагрэты, а ў рэпліцы кэш трохі адстае.
Ды гэта праўда. У pcache не будзе блокаў дадзеных, якія вы жадаеце, у real cache не будзе інфармацыі аб табліцах, якія вы жадаеце, у планах не будзе распарсенных запытаў, наогул нічога не будзе.
І калі ў вас ёсць нейкі кластар, і вы дадаеце туды новую рэпліку, то пакуль яна стартуе, у ёй усё дрэнна, т. е. яна нарошчвае свой кэш.
Я зразумеў ідэю. Правільным падыходам было б запусціць невялікі працэнт запытаў спачатку на рэпліку, якія б прагрэлі кэш. Грубіянска кажучы, у нас ёсць умова, што мы павінны адставаць не больш, чым на 10 секунд ад майстра. І гэта ўмова ўключаць не адной хваляй, а плаўна для некаторых кліентаў.
Так, павялічваць вагу.
Гэта добрая ідэя. Але спачатку трэба рэалізаваць гэтае адключэнне. Спачатку трэба выключыцца, а потым падумаем, як уключыцца. Гэта выдатная фіча, каб плаўна ўключацца.
У nginx ёсць такая опцыя slowly start
у кластары для сервера. І ён паступова нарошчвае нагрузку.
Так, выдатная ідэя, паспрабуем, калі дойдзем да гэтага.
Крыніца: habr.com