- Заўчаснай аптымізацыі працы з базай дадзеных
- Заўчаснай аптымізацыі УСЯГО ДАДАТКІ У ЦЭЛЫМ
- ПРА хіпстэры і срэбныя кулю
- НЕ перагінаць
Мы ўжо казалі пра тое, што такое хайлоад і які ён бывае, а цяпер хацелася б закрануць дастаткова хворы тэмы - ці варта да яго рыхтавацца маладым кампаніям, якія толькі пачынаюць распрацоўваць свой прадукт. І калі варта, то на якім этапе распрацоўкі.
Зразумелая справа, што ўсім распрацоўнікам, як людзям тэхнічным, хочацца цікавых і складаных задач і архітэктур, але на старце важны баланс тэхналогій і кліенцкіх фіч прадукту. З аднаго боку, трэба як мага хутчэй выносіць новую функцыянальнасць, з другога - не апынуцца ў кропцы, калі нічога не працуе з-за складаных нагрузак і зрабіць нічога нельга.
Як бы авантурна гэта ні гучала - за пяць гадоў працы мы амаль не бачылі, каб кампанія сапраўды апыналася ў такой сітуацыі, што зрабіць было ўжо нічога нельга (за рэдкімі выключэннямі). Затое бачылі мноства выпадкаў, калі кампаніі трацілі свой час на тое, каб рыхтавацца да жудаснай наведвальнасці, да якой у выніку банальна не дажывалі.
Як гаварыў дзядуля Пуга, заўчасная аптымізацыя - корань усіх злы. І ў дадзеным артыкуле мы хочам прайсціся па яе трох відах, якія бачым часцей за ўсё ў вебразработке. гэта:
• заўчасная аптымізацыя працы з базай даных;
• заўчасная аптымізацыя ўсяго прыкладання ў цэлым;
• празмернае захапленне хипстерскими тэхналогіямі ў надзеі знайсці сярэбраную кулю.
Заўчаснай аптымізацыі працы з базай дадзеных
Мы часта бачым, як стартапы чакаюць, што з першага ж дня асноўная нагрузка ляжа на базу дадзеных, якая не зможа справіцца з расце аб'ёмам запытаў і пакладзе праект.
У адной сяброўскай нам кампаніі, якой, на жаль, цяпер ужо няма, распрацоўшчыкі сыходзілі з таго, што гіганцкая колькасць дадзеных будзе ўжо на старце. І распрацоўку праекта пачалі з планавання архітэктуры, якая дала б магчымасць лёгка і практычна балансаваць дадзеныя паміж любой колькасцю сервераў. Пры гэтым схема ўлічвала магчымасць дадання новай Шардэн базы дадзеных на лета.
Распрацоўшчыкі вярталіся да гэтай падсістэме некалькі разоў на працягу двух гадоў - яна не была цалкам гатовая, а распрацоўшчыкі, звязаныя з прадуктовай часткай, рэгулярна мянялі схемы БД. У выніку праект быў зачынены, а сілы, якія маглі б быць кінутыя на ўдасканаленне прадуктовай часткі, былі выдаткаваныя на стварэнне падсістэмы, якую ніколі не давялося выкарыстоўваць.
На справе - шардинг неабходны як рашэнне двух праблем:
1. Аперацыі з БД ва ўмовах вялізнага аб'ёму дадзеных.
2. Маштабаванне нагрузкі на дыскавую запіс.
Асобна хацелася б адзначыць: у 99 з 100 выпадкаў (і ва ўмовах шырокай даступнасці SSD ў нашы дні) задачы маштабавання запісу ўзнікаюць далёка не адразу. Каб кантэнт ствараўся, карыстальніка трэба зацікавіць. Пры гэтым вялікія аб'ёмы дадзеных у вашай сістэме таксама не апынуцца нечакана і адразу - амаль напэўна ў вас будзе час на мадыфікацыю архітэктуры ў працэсе працы сістэмы так, каб яна магла маштабавацца па запісе.
Што можа гэтаму перашкодзіць і што сапраўды варта зрабіць у пачатку? Мы скажам крамольную рэч: варта быць вельмі асцярожным з выкарыстаннем любых абстракцый доступу да базы дадзеных. Так, ORM - гэта клёва і зручна, але, калі гаворка зойдзе пра тое, што запыт трэба раскідаць па двух розных месцах, - табе прыйдзецца дакапацца да самых глыбінь выкарыстоўванага ORM, каб зразумець, як гэта рэалізаваць. Мы часта бачым, як, здавалася б, простая задача мадыфікацыі ва ўмовах генеравання SQL-запытаў ператвараецца ў сапраўднае пекла.
Другая аптымізацыя з пункту гледжання праграміста, якую можна зрабіць, - гэта адразу прадугледзець, што сервераў можа быць некалькі, і ў момант выбару дадзеных дапусціць тое, што SQL-запыт можа быць выкананы на адным з некалькіх сервераў. Гэта значыць: у цябе ёсць аб'ект доступу да БД, і ў цябе ёсць SQL-запыт, які ты хочаш выканаць. Добраму, у тым месцы, дзе ты выконваеш гэты запыт да сервера, ты павінен мець магчымасць непасрэдна выбраць сервер, да якога звяртаешся.
І яшчэ трохі пра ORM: ва ўмовах высокіх нагрузак не можа атрымацца нармальнага падзелу сфер ўплыву - праграміст праграмуе, а адміністратар БД адмініструе БД. Па сутнасці, праца праграміста павінна ўжо зыходзіць з спецыфікі працы з БД, паколькі нават невялікія мадыфікацыі (фарсіраванне выкарыстання індэксаў, змена запыту пад спецыфіку аптымізатар базы дадзеных) могуць даць велізарны прырост прадукцыйнасці.
Прастата і даступнасць ORM ізалююць усю гэтую спецыфіку ад распрацоўніка і даюць шанец згенераваць шалёны запыт, які для праграміста будзе выглядаць цалкам нармальным.
На адным з праектаў - сайце з пытаннямі і адказамі, напісанай на Джанг, - мы бачылі, як спіс пытанняў на працягу нейкага колькасці кода перад яго атрыманнем быў абмежаваны побач крытэраў. З пункту гледжання праграміста усё выглядала больш-менш ОК - час ад часу да аб'екта спісу проста дапаўняўся новы крытэрый. У выніку ж ORM Джанг генераваў запыт на 25 group by, якія экспанентна стваралі нагрузку на базу па меры росту аб'ёму апрацоўваных дадзеных. І калі б запыт быў у выглядзе простага SQL - яшчэ заставаўся шанец падумаць, як аптымізаваць працэдуру, але ў гэтым выпадку ўсё было моцна ўскладненае.
Напрыканцы пра частку з аптымізацыяй БД. Як мы ўжо сказалі, мы часцей бачым нагрузку на чытанне, чым на запіс. Арганізаваць вялікую нагрузку на запіс - гэта асобны поспех :). А нагрузку на чытанне можна балансаваць наогул без асаблівых змен з боку кода. Калі мы гатовыя да таго, што падчас выканання запыту мы можам выбраць сервер, то, калі нам трэба балансаваць чытанне, мы можам проста стварыць n-нае колькасць slave-сервераў. А пры выкананні Селекта рандомные выбіраць адзін з сервераў, на якім ужо і выконваць гэты селект. А запіс вырабляць толькі ў адзін асобны master.
Заўчаснай аптымізацыі УСЯГО ДАДАТКІ У ЦЭЛЫМ
Гэтая гісторыя пачынаецца гэтак жа: адны нашы сябры чакалі сто мільёнаў карыстальнікаў. Паслухалі даклад пра тое, як усё ўладкована ў Яндэксе, і захацелі зрабіць у сябе гэтак жа. Вырашылі, што nginx будзе збіраць вэб-старонкі па шаблонах у XSLT / XML, што апісвае агульную структуру кампанентаў на старонцы. Пры запыце nginx парс файл, бачыць, якія выкарыстоўваюцца кампаненты, і па кожным кампаненце звяртаецца на бэкенд
за яго отрендеренные версіяй, перадаючы ідэнтыфікатар сесіі, каб захаваць стан. А адпаведна, бэкенд ўсёй платформы разумее, як атрымліваць такія запыты і генераваць выснову кампанента.
У выніку стварэнне гэтага рашэння заняло больш за год, прыцягнутыя C-распрацоўшчыкі запыталі перадаплату, але так і не зрабілі модуль, які б рэалізоўваў дадзены функцыянал у nginx. Зрэшты, ён і не спатрэбіўся, бо пасля двух гадоў распрацоўкі праект прыйшлося звярнуць.
У наш XXI стагоддзе хмарных тэхналогій, дзе CPU-рэсурсы маштабуюцца даволі танна па вертыкалі, а балансировщики нагрузкі ўключаюцца за вельмі кароткі час, ствараць загадзя нейкі спецыфічны код для балансавання прыкладання, на наш погляд, здаецца лішняй працай. Што вы сапраўды можаце зрабіць, так гэта прадугледзець, каб сесіі карыстачоў не былі прывязаныя да канкрэтнай вебмашине, і пасля гэтага проста кланаваць то колькасць вебинстансов, якое вам трэба ў чаканні аптымізацыі кода.
Іншая крайнасць, якую мы сустракалі ў сваёй практыцы, - гэта ўскладненне працы са статычным змесцівам, загружаным карыстальнікамі. У разліку на высокую нагрузку распрацоўшчыкі ствараюць падтрымку кластара nginx-сервераў з WebDAV-модулем. Кожны файл, загружаны карыстальнікам, спачатку клаўся на прамежкавы сервер, а следам адпраўляўся на WebDAV-сервер, адкуль пазней аддаваўся nginx'ом. Інфармацыя пра месца захоўвання гэтага файла захоўвалася ў базе. Рэальная нагрузка на гэты праект так і не прыйшла.
Сапраўды сур'ёзнай праблемай, на наш погляд, для большасці праектаў з'яўляецца толькі поўная адсутнасць якога-небудзь прынцыпу захоўвання файлаў - калі ўсё складаецца ў адну дырэкторыю. І калі ў адзін цудоўны дзень ты разумееш, што файлаў стала пад 70 тысяч і ext4 не дае табе запісваць новыя, ты альбо прыдумваеш разумную схему размеркавання файлаў, альбо пераязджаеш, да прыкладу на XFS. У другім выпадку цябе ўжо нішто не ўратуе.
Як мы прапануем вырашаць гэтае пытанне ўсім кліентам:
1. Калі ёсць падзел «гарачых» і «халодных» дадзеных па часе (свежыя фатаграфіі Укантакце прагортваюць часцей, чым старыя), а паток заліваю дадзеных прыкладна аднолькавы - пры загрузцы файлаў захоўвай файлы ў дырэкторыі, створанай з даты / часу моманту загрузкі. У залежнасці ад колькасці гэта можа быць проста разбіццё па днях, а можа быць разбіццё па гадзінах. Зноў жа так будзе прасцей выдаляць старыя файлы пры неабходнасці.
2. Калі падзелу дадзеных на свежыя і не вельмі няма, то можна вылічваць два розных лічбавых хэша ад імя файла, а затым выкарыстоўваць іх у нейкай структуры каталогаў, усярэдзіне якой ужо складваць сам файл.
Але што рабіць, калі мы баімся, што сэрвэр не вывезе нагрузкі на чытанне? На першым этапе нас уратуе lsyncd, які дапаможа размеркаваць статыку па некалькіх асобных серверам і тым самым размеркаваць нагрузку на яе чытанне. А так як статыка ўсюды аднолькавая, то чытаць яе можна з любога сервера. Пры неабходнасці можна будзе лёгка дадаваць у схему дадатковыя магутнасці, пакуль праграмісты нарэшце не прыдумаюць больш тонкую схему. Але будзь асцярожны - памятай, што няма нічога больш пастаяннага, чым нейкі часовы мыліца. Ад іх абавязкова трэба будзе пазбавіцца.
ПРА хіпстэры і срэбныя кулю
Не варта зламаючы галаву кідаць правераныя часам і мільярдамі RPS'ов рашэння дзеля новых модных фішачак, у надзеі знайсці выратаванне ад усіх бед адразу. Часцяком аказваецца, што нават калі нейкія звышновыя методыкі і тэхналогіі вырашаюць нейкія з тваіх бягучых праблем, то пры гэтым яны дадаюць ладную долю новых, нават пра патэнцыйную магчымасць якіх ты мог ніколі не задумвацца. узяць,
да прыкладу, тыя ж NoSQL базы дадзеных. У захапленні NoSQL як панацэяй ад праблем з БД на самай справе ёсць вельмі шмат падводных камянёў. Напрыклад, на большасці NoSQL рашэнняў сінхранізацыя дадзеных на дыск - гэта глабальны лок, падчас якога праца з базай дадзеных вельмі цяжкая. Пры выкарыстанні радыскі, калі знаходзяцца ў ім дадзеныя табе патрэбныя, у цябе ёсць два выйсці:
1. Мець на асобнай машыне слейв, які будзе перыядычна дамп дадзеныя.
2. Адключыць дамп на майстры, не рабіць слейв, пастаянна маліцца, што нічога не зваліцца.
Па сутнасці, дзве галоўныя праблемы ўсіх новых тэхналогій вынікаюць адна з адной:
1. Сырасць рашэння.
2. Адсутнасць базы ведаў па існуючых праблемах.
Калі ў цябе ёсць праблема з MySQL і Postgres, ты можаш напісаць пра яе ў гугле і амаль напэўна знойдзеш мільён людзей, якія сустракаліся з падобнай да цябе. Калі ж праблема звязана з нейкай свежай тэхналогіяй, вялікі рызыка, што давядзецца выходзіць на распрацоўніка і разам разбірацца, што да чаго. Мы самі аднойчы занадта захапіліся падобнымі рэчамі (і гэта адбылося нават ужо на адносна вядомым і доўга распрацоўваным Openstack'е) - замест звыклых метадаў віртуалізацыі хацелася мець магчымасць кіраваць віртуальнымі машынамі «як ў Амазоніі». Для гэтага мы абралі Openstack, з якім пакутавалі на працягу наступнага месяца. Асноўная прычына пакут - волкасць і неабходнасць падтрымкі. Для таго каб запусціць віртуальную машыну ў Openstack, працуюць пяць Python-дэманаў, узаемадзеянне паміж якімі ідзе праз RabbitMQ, а код пастаянна мяняецца. Зразумелая справа, што зламацца там можа ўсё што заўгодна, і яно ламаецца.
НЕ перагінаць
З іншага боку, быць зусім ужо рэтраградам таксама небяспечна. Давай ўспомнім Perl-распрацоўнікаў (мы зусім не жадаем пакрыўдзіць Perl-распрацоўнікаў), якія казалі, што Perl лепш, чым PHP, Perl лепш Python, Perl лепш Ruby і гэтак далей. І зараз мы бачым велізарную колькасць Perl-распрацоўшчыкаў, рынак для якіх паступова зачыняецца. Як жа быць?
Галоўнае - знайдзі каго-небудзь, хто прайшоў цярністы шлях абранай тэхналогіі да цябе :). У вельмі многіх людзей ёсць дастаткова вольнага часу, а стартапы, якія вылучаюць па два гады на ўсякія тэхналагічныя рашэнні, заўсёды будуць існаваць. Абраў хітрую тэхналогію, пра якую ўсе пішуць? Знайдзі рабят, якія ўжо спрабавалі і дапамогуць, напрыклад нас :)
Але што рабіць, калі мы баімся, што сэрвэр не вывезе нагрузкі на чытанне?
Як жа быць?
Абраў хітрую тэхналогію, пра якую ўсе пішуць?