Рэзервовае капіраванне, частка 1: Прызначэнне, агляд метадаў і тэхналогій

Рэзервовае капіраванне, частка 1: Прызначэнне, агляд метадаў і тэхналогій
Навошта трэба рабіць рэзервовыя копіі? Бо абсталяванне вельмі і вельмі надзейнае, да таго ж ёсць "аблокі", якія па надзейнасці лепш фізічных сервераў: пры правільнай наладзе "хмарны" сервер папросту перажыве адмову інфраструктурнага фізічнага сервера, а з пункту гледжання карыстальнікаў сэрвісаў, будзе невялікі, ледзь прыкметны скачок часу абслугоўвання. Да таго ж дубляванне інфармацыі часта патрабуе аплаціць "лішні" працэсарны час, дыскавую нагрузку, трафік сеткі.

Ідэальная праграма працуе хутка, не цячэ па аператыўнай памяці, не мае дзюр і не існуе.

-Невядомы

Паколькі праграмы ўсё яшчэ пішуцца бялковымі распрацоўшчыкамі, а працэс тэставання часцяком адсутнічае, плюс пастаўка праграм вельмі рэдка адбываецца з ужываннем "best practices" (якія самі па сабе таксама праграмы, а такім чынам, неідэальныя), сістэмным адміністратарам часцей за ўсё даводзіцца вырашаць задачы, якія гучаць коратка, але ёміста: "вярнуць, як было", "прывесці базу да нармальнай працы", "павольна працуе - адкочваем", а таксама маё каханае "не ведаю што, але адрамантуй".

Акрамя лагічных памылак, якія вылазяць у выніку нядбайнай працы распрацоўнікаў, або збегу акалічнасцяў, а таксама няпоўнага ведання ці неразумення дробных асаблівасцяў пабудовы праграм - у тым ліку злучных і сістэмных, уключаючы аперацыйныя сістэмы, драйвера і прашыўкі, - ёсць яшчэ і іншыя памылкі. Напрыклад большасць распрацоўшчыкаў належыць на рантайм, зусім забываючы аб фізічных законах, абыйсці якія з дапамогай праграм усё яшчэ немагчыма. Гэта і бясконцая надзейнасць дыскавай падсістэмы і наогул любой падсістэмы захоўвання дадзеных (уключаючы аператыўную памяць і кэш працэсара!), і нулявое час апрацоўкі на працэсары, і адсутнасць памылак пры перадачы па сетцы і пры апрацоўцы на працэсары, і затрымкі сеткі, якія роўныя 0. Не варта грэбаваць і праславутым дэдлайнам, бо калі да яго не паспець - будуць праблемы лепш нюансаў працы сеткі і дыска.

Рэзервовае капіраванне, частка 1: Прызначэнне, агляд метадаў і тэхналогій

Як жа быць з праблемамі, якія ўстаюць у поўны рост і навісаюць над каштоўнымі дадзенымі? Жывых распрацоўшчыкаў замяніць няма чым, ды і не факт, што можна будзе ў бліжэйшы час. З іншага боку, цалкам даказаць, што праграма будзе працаваць як задумана, пакуль што атрымалася толькі ў некалькіх праектаў, і зусім не абавязкова можна будзе ўзяць і прымяніць доказы на іншыя, падобныя праекты. Таксама падобныя доказы займаюць процьму часу, і патрабуюць асаблівых навыкаў і ведаў, а гэта практычна зводзіць да мінімуму магчымасць іх прымянення з улікам дэдлайнаў. Да таго ж мы яшчэ не ўмеем у звышхуткую, танную і бясконца надзейную тэхналогію захоўвання, апрацоўкі і перадачы інфармацыі. Падобныя тэхналогіі, калі і існуюць, то ў выглядзе канцэптаў, альбо - часцей за ўсё - толькі ў фантастычных кнігах і фільмах.

Добрыя мастакі капіююць, вялікія мастакі крадуць.

-Пабла Пікасо.

Самыя ўдалыя рашэнні і дзіўна простыя рэчы звычайна адбываюцца там, дзе сустракаюцца абсалютна несумяшчальныя, на першы погляд, паняцці, тэхналогіі, веды, вобласці навук.

Напрыклад, у птушак і ў самалётаў ёсць крылы, аднак нягледзячы на ​​функцыянальнае падабенства - прынцып дзеяння ў некаторых рэжымах супадае, і тэхнічныя праблемы вырашаюцца аналагічна: полыя косткі, выкарыстанне трывалых і лёгкіх матэрыялаў і да т.п., - вынікі абсалютна розныя, хоць і вельмі падобныя. Лепшыя ўзоры, якія мы назіраем у нашай тэхніцы, таксама па большай частцы запазычаныя ў прыроды: герметычныя адсекі ў караблёў і падводных лодак - прамая аналогія з кольчата чарвякамі; пабудова raid-масіваў і праверка цэласнасці дадзеных - дубляванне ланцужкі ДНК; а таксама парныя органы, незалежнасць працы розных органаў ад ЦНС (аўтаматыя працы сэрца) і рэфлексы - аўтаномныя сістэмы ў Інтэрнэт. Вядома браць і прымяняць гатовыя рашэнні «ў лоб» багата праблемамі, але хто ведае, можа, іншых рашэнняў вось і няма.

Ведаць бы, дзе ўпадзеш - саломкі падаслаў бы!

-Беларуская народная прыказка

Значыць, рэзервовыя копіі жыццёва неабходны тым, хто жадае:

  • Мець магчымасць аднавіць працу сваіх сістэм з мінімальнымі прастоямі, а то і зусім без іх
  • Смела дзейнічаць, таму што ў выпадку памылкі заўсёды ёсць магчымасць адкату.
  • Звесці да мінімуму наступствы наўмыснага псуты дадзеных

Тут - трохі тэорыі

Любая класіфікацыя адвольная. Прырода не класіфікуе. Класіфікуем мы, бо для нас так зручней. І класіфікуем па дадзеных, якія мы бярэм таксама адвольна.

- Жан Брулер

Незалежна ад фізічнага спосабу захоўвання лагічнае захоўванне дадзеных можна ўмоўна падзяліць па 2 спосабах доступу да гэтых дадзеных: блокавае і файлавае. Такое дзяленне ў апошні час вельмі размыта, бо чыста блокавых, як і чыста файлавых, лагічных сховішчаў не існуе. Аднак для прастаты будзем лічыць, што яны ёсьць.

Блокавае захоўванне дадзеных мае на ўвазе, што ёсць фізічная прылада, куды запісваюць дадзеныя некаторымі фіксаванымі порцыямі, блокамі. Доступ да блокаў ідзе па некаторым адрасе, кожнаму блоку адпавядае свой адрас у межах прылады.

Рэзервовая копія звычайна робіцца шляхам капіравання блокаў дадзеных. Для забеспячэння цэласнасці дадзеных на момант капіявання прыпыняецца запіс новых блокаў, а таксама змена існых. Калі браць аналогію з звычайнага свету - бліжэй за ўсё шафа з аднолькавымі пранумараванымі вочкамі.

Рэзервовае капіраванне, частка 1: Прызначэнне, агляд метадаў і тэхналогій

Файлавае захоўванне дадзеных па прынцыпе лагічнай прылады блізка да блокавага і часцяком арганізуецца па-над. Важныя адрозненні - наяўнасць іерархіі захоўвання і чалавеказразумелыя імёны. Вылучаецца абстракцыя ў выглядзе файла - найменнай вобласці дадзеных, а таксама каталога - адмысловага файла, у якім захоўваюцца апісанні і доступы да іншых файлаў. Файлы могуць забяспечвацца дадатковымі метададзенымі: час стварэння, сцягі доступу і да т.п. Рэзервуюць звычайна так: шукаюць змененыя файлы, потым капіююць іх у іншае, аднолькавае па структуры файлавае сховішча. Цэласнасць дадзеных звычайна рэалізуюць шляхам адсутнасці файлаў, у якія ідзе запіс. Метададзеныя файлаў рэзервуюцца аналагічна. Бліжэйшая аналогія - бібліятэка, у якой ёсць раздзелы з рознымі кнігамі, а таксама ёсць каталог з чалавеказразумелымі імёнамі кніг.

Рэзервовае капіраванне, частка 1: Прызначэнне, агляд метадаў і тэхналогій

У апошні час часам апісваюць яшчэ адзін варыянт, з якога, у прынцыпе, і пачалося файлавае захоўванне дадзеных, і ў якога ёсць тыя ж архаічныя рысы: аб'ектнае захоўванне дадзеных.

Ад файлавага захоўвання адрозніваецца тым, што не мае ўкладзенасці больш аднаго (плоская схема), а імёны файлаў хоць і чалавекачытальныя, але ўсё ж больш прыстасаваны для апрацоўкі машынамі. Пры рэзервовым капіяванні аб'ектныя сховішчы часцей за ўсё апрацоўваюць падобна файлавым, але зрэдку ёсць і іншыя варыянты.

- Ёсць два віды сістэмных адміністратараў, тыя хто не робіць рэзервовыя копіі, і тыя, хто УЖО робіць.
- На самай справе тры віды: ёсць яшчэ тыя, хто правярае, што рэзервовыя копіі можна аднавіць.

-Невядомы

Таксама варта разумець, што сам працэс рэзервовага капіявання дадзеных ажыццяўляецца праграмамі, таму яму ўласцівыя ўсё тыя ж мінусы, як і іншай праграме. Каб прыбраць (не выключыць!) залежнасць ад чалавечага фактару, а таксама асаблівасцяў - якія па асобнасці не моцна ўплываюць, але разам могуць даць адчувальны эфект, - ужываюць т.зв. правіла 3-2-1. Ёсць шмат варыянтаў, як яго расшыфраваць, але мне больш падабаецца наступная трактоўка: захоўваць трэба 3 наборы адных і тых жа дадзеных, 2 наборы трэба захоўваць у розных фарматах, а таксама 1 набор трэба мець на геаграфічна выдаленым сховішчы.

Пад фарматам захоўвання трэба разумець наступнае:

  • Калі ёсць залежнасць ад фізічнага спосабу захоўвання - змяняем фізічны спосаб.
  • Калі ёсць залежнасць ад лагічнага спосабу захоўвання - змяняем лагічны спосаб.

Для дасягнення максімальнага эфекту правіла 3-2-1 рэкамендуецца мяняць фармат захоўвання абодвума спосабамі.

З пункту гледжання гатоўнасці рэзервовай копіі па яе прамым прызначэнні - аднаўленню працаздольнасці, - адрозніваюць "гарачыя" і "халодныя" рэзервовыя копіі. Гарачыя ад халодных адрозніваюцца толькі адным: яны адразу ж гатовы да працы, у той час як халодныя для аднаўлення патрабуюць некаторых дадатковых дзеянняў: расшыфроўкі, вымання з архіва і да т.п.

Не варта блытаць гарачыя і лядоўні копіі з online і offline копіямі, якія маюць на ўвазе фізічную ізаляцыю дадзеных, і ў сутнасці, з'яўляюцца іншай прыкметай класіфікацыі спосабаў рэзервовага капіявання. Так offline копія – не падлучаная непасрэдна да сістэмы, дзе яе трэба аднавіць, – можа быць як гарачай, так і халоднай (з пункту гледжання гатоўнасці да аднаўлення). Online копія можа быць даступная непасрэдна тамака, дзе яе трэба аднаўляць, і часцей за ўсё з'яўляецца гарачай, але бываюць і лядоўні.

Акрамя таго, не варта забываць, што сам працэс стварэння рэзервовых копій звычайна не заканчваецца на стварэнні адной рэзервовай копіі, а копій можа быць дастаткова вялікі лік. Такім чынам, трэба адрозніваць поўныя рэзервовыя копіі, г.зн. тыя, якія аднаўляюцца незалежна ад іншых рэзервовых копій, а таксама рознасныя (інкрыментальныя, дыферэнцыяльныя, дэкрэментальныя і да т.п.) копіі - тыя, якія не могуць быць адноўлены самастойна і патрабуюць папярэдняга аднаўлення адной або некалькіх іншых рэзервовых копій.

Рознасныя інкрыментальныя копіі - спроба зэканоміць памер прасторы для захоўвання рэзервовых копій. Такім чынам, у рэзервовую копію пішуцца толькі змененыя дадзеныя з мінулай рэзервовай копіі.

Рознасныя дэкрэментальныя ствараюцца з той жа мэтай, але крыху іншым шляхам: робіцца поўная рэзервовая копія, але рэальна захоўваецца толькі розніца паміж свежай копіяй і папярэдняй.

Асобна варта разгледзець працэс рэзервовага капіявання па-над сховішчам, якое падтрымлівае адсутнасць захоўвання дублікатаў. Такім чынам, калі пісаць поўныя рэзервовыя копіі па-над ім, рэальна будзе запісана толькі розніца паміж рэзервовымі копіямі, аднак працэс аднаўлення рэзервовых копій будзе адбывацца аналагічна аднаўленню з поўнай копіі і цалкам празрыста.

Quis custodiet ipsos custodes?

(Хто засцеражэ саміх вартаўнікоў? - Лац.)

Вельмі непрыемна, калі рэзервовых копій няма, аднак значна горш, калі рэзервовая копія быццам бы і зроблена, але пры аднаўленні высвятляецца, што яна не можа быць адноўлена, таму што:

  • Цэласнасць зыходных дадзеных была парушана.
  • Сховішча з рэзервовымі копіямі пашкоджана.
  • Аднаўленне працуе вельмі павольна, нельга карыстацца дадзенымі, якія часткова адноўлены.

Правільна пабудаваны працэс рэзервовага капіявання абавязаны ўлічваць падобныя заўвагі, асабліва першыя два.

Цэласнасць зыходных даных можна гарантаваць некалькімі спосабамі. Найбольш часта выкарыстоўваюцца наступныя: а) стварэнне злепкаў файлавай сістэмы на блокавым узроўні, б) «замарозка» станы файлавай сістэмы, у) адмысловая блокавая прылада з захоўваннем версій, г) паслядоўны запіс файлаў ці блокаў. Таксама прымяняюцца кантрольныя сумы, каб забяспечваць праверку дадзеных пры аднаўленні.

Пашкоджанні сховішчы таксама можна выявіць з дапамогай кантрольных сум. Дадатковы метад - ужыванне спецыялізаваных прылад, альбо файлавых сістэм, у якіх нельга змяняць ужо запісаныя дадзеныя, але можна дапісваць новыя.

Для паскарэння аднаўлення прымяняецца аднаўленне дадзеных з некалькімі працэсамі для аднаўлення - пры ўмове, што няма "бутэлькавага рыльца" ў выглядзе павольнай сеткі або няхуткай дыскавай сістэмы. Для таго, каб абыйсці сітуацыю з часткова адноўленымі дадзенымі, можна разбіць працэс рэзервовага капіявання на адносна невялікія подзадачи, кожная з якіх выконваецца асобна. Такім чынам, з'яўляецца магчымасць паслядоўна аднавіць працаздольнасць з прагназаваннем часу аднаўлення. Дадзеная праблема часцей за ўсё ляжыць у абмежаванай плоскасці (SLA), таму не будзем спыняцца на гэтым падрабязна.

Ведае толк у рэзкіх затаўках не той, хто дадае іх у кожную страву, але той, хто ніколі не дадасць у яго нічога лішняга.

-У. Сіняўскі

Практыка ў частцы ўжывальнага ПЗ у сістэмных адміністратараў можа адрознівацца, але агульныя прынцыпы ўсё роўна, так ці інакш, тыя ж, у прыватнасці:

  • Настойліва рэкамендуецца прымяняць гатовыя рашэнні.
  • Праграмы павінны працаваць прадказальна, г.зн. не павінна быць недакументаваных асаблівасцяў ці вузкіх месцаў.
  • Настройка кожнай праграмы павінна быць простай настолькі, каб не даводзілася кожны раз чытаць кіраўніцтва ці шпаргалку.
  • Рашэнне па магчымасці павінна быць універсальным, т.я. сервера па сваіх апаратных характарыстыках могуць адрознівацца вельмі і вельмі.

Для зняцця рэзервовых копій з блокавых прылад ёсць наступныя распаўсюджаныя праграмы:

  • dd, знаёмая ветэранам сістэмнага адміністравання, сюды ж адносяцца падобныя праграмы (тая ж dd_rescue, напрыклад).
  • Убудаваныя ў некаторыя файлавыя сістэмы абслуговыя праграмы (утыліты), якія ствараюць злепак (dump) файлавай сістэмы.
  • Усяедныя ўтыліты; напрыклад, partclone.
  • Уласныя, часта ўласніцкія, рашэнні; напрыклад, NortonGhost і пазнейшыя.

Для файлавых сістэм задача рэзервовага капіявання часткова вырашаецца з дапамогай метадаў, якія ўжываюцца для блокавых прылад, аднак задачу можна вырашыць і больш эфектыўна, выкарыстаючы, напрыклад:

  • Rsync, універсальную праграму і пратакол для сінхранізацыі стану файлавых сістэм.
  • Убудаваныя сродкі для архівацыі (ZFS).
  • Іншыя сродкі для архівацыі; самы папулярны прадстаўнік - tar. Ёсць і іншыя, напрыклад, dar - замена tar з арыентацыяй на сучасныя сістэмы.

Асобна варта згадаць аб праграмных сродках забеспячэння кансістэнтнасці дадзеных пры стварэнні рэзервовых дзід. Часцей за ўсё ўжываюць наступныя варыянты:

  • Мантаванне файлавай сістэмы ў рэжым толькі чытанне (ReadOnly), або замарожванне файлавай сістэмы (freeze) - метад ужыем абмежавана.
  • Стварэнне злепкаў стану файлавай сістэм або блокавай прылады (LVM, ZFS).
  • Ужыванне іншых сродкаў для арганізацыі злепкаў, нават у тых выпадках, калі папярэднія пункты не могуць быць забяспечаны па якіх-небудзь чынніках (праграмы выгляду hotcopy).
  • Тэхніка капіявання пры змене (CopyOnWrite), аднак яна часцей за ўсё прывязана да выкарыстоўванай ФС (BTRFS, ZFS).

Такім чынам, для невялікага сервера трэба забяспечыць схему рэзервовага капіявання, якая адказвае наступным патрабаванням:

  • Простая ў працы - не патрабуецца асаблівых дадатковых дзеянняў пры працы, мінімальныя дзеянні па стварэнні і аднаўленні копій.
  • Універсальная - працуе як на вялікіх, так і на малых серверах; гэта важна пры росце колькасці сервераў або маштабаванні.
  • Усталёўваецца пакетным мэнэджарам, або ў адну-дзве каманды выгляду «спампаваць і распакаваць».
  • Стабільная - выкарыстоўваецца стандартны ці ўжо даўно ўстояны фармат захоўвання.
  • Хуткая ў працы.

Прэтэндэнты з тых, хто больш-менш адказвае патрабаванням:

  • rdiff-рэзервовае капіраванне
  • rsnapshot
  • адрыжка
  • duplicati
  • двудушнасць
  • няхай дуп
  • даваць
  • zbackup
  • restic
  • borgbackup

Рэзервовае капіраванне, частка 1: Прызначэнне, агляд метадаў і тэхналогій

У якасці тэставага стэнда будзе прымяняцца віртуальная машына (на базе XenServer) з наступнымі характарыстыкамі:

  • 4 ядра 2.5 Ггц,
  • 16 гб аператыўнай памяці,
  • 50 гб hybrid storage (СХД з кэшаваннем на SSD у 20% ад памеру віртуальнай кружэлкі) у выглядзе асобнай віртуальнай кружэлкі без разметкі,
  • 200 Мбітс канал у Інтэрнэт.

У якасці сервера-прымача рэзервовых дзід будзе ўжывацца практычна такая ж машына, толькі з цвёрдай кружэлкай на 500 гб.

Аперацыйная сістэма - Centos 7 x64: разбіўка стандартная, дадатковая частка будзе выкарыстоўвацца як крыніца дадзеных.

У якасці зыходных дадзеных возьмем сайт на wordpress, з медыяфайламі памерам 40 гігабайт, базай дадзеных на mysql. Бо віртуальныя сервера вельмі моцна адрозніваюцца па характарыстыках, а таксама для лепшай узнаўляльнасці, тут ёсць

вынікі тэсціравання сервера з дапамогай sysbench.sysbench -threads=4 -time=30 -cpu-max-prime=20000 cpu run
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Запуск тэсту з наступнымі опцыямі:
Колькасць нітак: 4
Initializing random number generator з бягучага часу

Prime numbers limit: 20000

Initializing worker threads…

Ніткі пачаліся!

Хуткасць працэсара:
events per second: 836.69

Прапускная здольнасць:
events/s (eps): 836.6908
time elapsed: 30.0039s
total number of events: 25104

Latency (ms):
мін: 2.38
avg: 4.78
максімум: 22.39
95th percentile: 10.46
сума: 119923.64

Тэмы справядлівасць:
events (avg/stddev): 6276.0000/13.91
execution time (avg/stddev): 29.9809/0.01

sysbench -threads=4 -time=30 -memory-block-size=1K -memory-scope=global-memory-total-size=100G
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Запуск тэсту з наступнымі опцыямі:
Колькасць нітак: 4
Initializing random number generator з бягучага часу

Running memory speed test with following options:
block size: 1KiB
total size: 102400MiB
operation: read
scope: global

Initializing worker threads…

Ніткі пачаліся!

Total operations: 50900446 (1696677.10 per second)

49707.47 MiB transferred (1656.91 MiB/sec)

Прапускная здольнасць:
events/s (eps): 1696677.1017
time elapsed: 30.0001s
total number of events: 50900446

Latency (ms):
мін: 0.00
avg: 0.00
максімум: 24.01
95th percentile: 0.00
сума: 39106.74

Тэмы справядлівасць:
events (avg/stddev): 12725111.5000/137775.15
execution time (avg/stddev): 9.7767/0.10

sysbench -threads=4 -time=30 -memory-block-size=1K -memory-scope=global-memory-total-size=100G
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Запуск тэсту з наступнымі опцыямі:
Колькасць нітак: 4
Initializing random number generator з бягучага часу

Running memory speed test with following options:
block size: 1KiB
total size: 102400MiB
operation: write
scope: global

Initializing worker threads…

Ніткі пачаліся!

Total operations: 35910413 (1197008.62 per second)

35068.76 MiB transferred (1168.95 MiB/sec)

Прапускная здольнасць:
events/s (eps): 1197008.6179
time elapsed: 30.0001s
total number of events: 35910413

Latency (ms):
мін: 0.00
avg: 0.00
максімум: 16.90
95th percentile: 0.00
сума: 43604.83

Тэмы справядлівасць:
events (avg/stddev): 8977603.2500/233905.84
execution time (avg/stddev): 10.9012/0.41

sysbench -threads=4 -file-test-mode=rndrw -time=60 -file-block-size=4K -file-total-size=1G fileio run
sysbench 1.1.0-18a9f86 (using bundled LuaJIT 2.1.0-beta3)
Запуск тэсту з наступнымі опцыямі:
Колькасць нітак: 4
Initializing random number generator з бягучага часу

Extra file open flags: (адсутнасць)
128 files, 8MiB each
1GiB total file size
Block size 4KiB
Number of IO requests: 0
Read/Write ratio для злучаных парадкаў IO test: 1.50
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() на канцы тэсту, Enabled.
Using synchronous I/O mode
Doing random r/w test
Initializing worker threads…

Ніткі пачаліся!

Прапускная здольнасць:
read: IOPS=3868.21 15.11/15.84 MiB/s (XNUMX MB/s)
write: IOPS=2578.83 10.07/10.56 MiB/s (XNUMX MB/s)
fsync: IOPS=8226.98

Latency (ms):
мін: 0.00
avg: 0.27
максімум: 18.01
95th percentile: 1.08
сума: 238469.45

Дадзенай нататкай пачынаецца вялікі

цыкл артыкулаў аб рэзервовым капіяванні

  1. Рэзервовае капіраванне, частка 1: Навошта трэба рэзервовае капіраванне, агляд метадаў, тэхналогій
  2. Рэзервовае капіраванне, частка 2: Агляд і тэсціраванне rsync-based сродкаў рэзервовага капіявання
  3. Рэзервовае капіраванне, частка 3: Агляд і тэсціраванне duplicity, duplicaty, deja dup
  4. Рэзервовае капіраванне, частка 4: Агляд і тэсціраванне zbackup, restic, borgbackup
  5. Рэзервовае капіраванне, частка 5: Тэставанне bacula і veeam backup for linux
  6. Рэзервовае капіраванне, частка 6: Параўнанне сродкаў рэзервовага капіявання
  7. Рэзервовае капіраванне, частка 7: Высновы

Крыніца: habr.com

Дадаць каментар