В чому полягає філософія затримки запису даних на диск?


72

В Linux завершене виконання команди, наприклад, cpабо ddне означає, що дані були записані на пристрій. Наприклад, потрібно зателефонувати syncабо викликати функцію "Безпечно видалити" або "Вийняти" на диску.

У чому полягає філософія такого підходу? Чому дані не записуються відразу? Чи немає небезпеки, що запис вийде з ладу через помилку вводу / виводу?


16
Пам'ятайте, що системні дзвінки для читання та запису можуть працювати з одним байтом одночасно, але дискові диски можуть читати або записувати лише блоки фіксованого розміру. Накладні витрати на байт за час вводу / виводу будуть нестерпними без буферизації. З буферизацією це терпимо.
Джонатан Леффлер

Відповіді:


47

У чому полягає філософія такого підходу?

Ефективність (краще використання характеристик диска) та продуктивність (дозволяє додатку продовжуватися відразу після запису).

Чому дані не записуються відразу?

Основна перевага полягає в тому, що ОС є вільною для переупорядкування та об'єднання операцій запису безперервного запису, щоб поліпшити використання їх пропускної здатності (менше операцій та менше бажань). Жорсткі диски ефективніші, коли вимагається невелика кількість великих операцій, тоді як додаткам, як правило, потрібна велика кількість невеликих операцій. Інша чітка оптимізація полягає в тому, що ОС також може видалити всі, крім останнього запису, коли один і той же блок записується кілька разів за короткий проміжок часу, або навіть видалити деякі записи всі разом, якщо зафіксований файл тим часом був видалений.

Ці асинхронні операції записи виконуються післяwrite того, як системний виклик повертається. Це друга і найпопулярніша перевага користувача. Асинхронний запис прискорює програми, оскільки вони вільні продовжувати свою роботу, не чекаючи, коли дані дійсно будуть на диску. Такий же тип буферизації / кешування також реалізований для операцій зчитування, де останні або часто читаються блоки зберігаються в пам'яті, а не знову читаються з диска.

Чи немає небезпеки, що запис вийде з ладу через помилку вводу-виводу?

Не обов'язково. Це залежить від використовуваної файлової системи та надмірності на місці. Помилка вводу / виводу може бути нешкідливою, якщо дані можна зберегти в іншому місці. Сучасні файлові системи, такі як ZFS, самостійно лікують блоки поганих дисків. Зауважте також, що помилки вводу / виводу не руйнують сучасні ОС. Якщо вони трапляються під час доступу до даних, вони просто повідомляються про це. Якщо вони трапляються під час доступу до структурних метаданих та ставлять під загрозу файлову систему, вони можуть бути перероблені лише для читання або зробити їх недоступними.

Існує також невеликий ризик втрати даних у разі аварії ОС, відключення живлення або відмови обладнання. Це причина, коли програми, які повинні бути на 100% впевнені, що дані є на диску (наприклад, бази даних / фінансові програми), роблять менш ефективними, але більш захищеними синхронними записами. Для пом'якшення впливу на продуктивність багато додатків все ще використовують асинхронні записи, але з часом синхронізують їх, коли користувач явно зберігає файл (наприклад, vim, текстові процесори.)

З іншого боку, дуже велика більшість користувачів та додатків не потребують і не дбають про безпеку, яку забезпечують синхронні записи. Якщо відбувається збій або відключення електроенергії, єдиний ризик - це втратити в гіршому випадку останні 30 секунд даних. Якщо немає фінансової транзакції або чогось подібного, що би означало витрати, набагато більші за 30 секунд свого часу, величезний приріст продуктивності (що не є ілюзією, але дуже реальним) асинхронний запис дозволяє значною мірою перевершити ризик.

Нарешті, синхронного запису недостатньо для захисту даних, записаних у будь-якому випадку. Якщо вашій програмі дійсно потрібно бути впевненим, що їхні дані не можуть бути втрачені, що б не трапилося, потрібно створити реплікацію даних на декількох дисках і в різних географічних місцях, щоб протистояти катастрофам, таким як пожежа, повені тощо.


Крім вартості, подумайте, чи зроблено щось, що спирається на збережені дані. Якщо я набираю текст у своєму романі, економлячи послідовно, а вимкнення електроенергії означає, що я втрачаю 30 секунд роботи, то незалежно від значення цих 30 секунд я принаймні відновлюсь до стану, який фактично стався під час введення тексту. , і я можу знову почати звідти. З іншого боку, якщо я натискаю кнопку "Зберегти", а потім перекреслюю щось із мого списку тодового паперу на своєму столі, тоді, коли я відновляюсь, у мене виникає невідповідність між жорстким диском та моїм папером. Це взагалі важче відновити з…
Стів Джессоп

1
... таким чином, як звичайний користувач, я можу захотіти синхронізувати файлову систему перед тим, як перейти "закінчити писати роман" зі свого списку todo, щоб переконатися, що я не думаю, що я зробив щось, що насправді не вдається. І саме тому бази даних і подібні потребують синхронних записів: навіть якщо вони втрачають дані, вони абсолютно повинні підтримувати послідовність.
Стів Джессоп

1
@SteveJessop Я погоджуюся з вашим прикладом, але я не очікував, що випадковий користувач синхронізується вручну. Якщо редактор, який використовувався для написання дорогоцінного роману, не викликає fsync або подібного, коли документ зберігається, це помилка, яку потрібно виправити, наприклад bugs.launchpad.net/ubuntu/+source/libreoffice/+bug/817326 . Я б використав vi (vim) для написання шахти, vim викликає fsync при збереженні за замовчуванням.
jlliagre

59

Це просто дає ілюзію швидкості програмам, яким насправді не доводиться чекати, поки запис не завершиться. Встановіть ваші файлові системи в режим синхронізації (який дає вам можливість миттєвого запису) і подивіться, як все повільно.

Іноді файли існують лише тимчасово ... програма виконує певну роботу і видаляє файл відразу після закінчення роботи. Якщо ви затримали ці записи, то, можливо, вам вдасться уникнути, коли ніколи їх не написали.

Чи немає небезпеки, що запис вийде з ладу через помилку вводу-виводу?

О, абсолютно. У такому випадку зазвичай вся файлова система переходить у режим лише для читання, і все жахливо. Але це трапляється рідко, загалом не втрачаючи переваг у виконанні.


Деякі контролери жорсткого диска мають резервне копіювання акумулятора, тому в разі відключення електроенергії невідомі дані зберігаються на контролері до відновлення живлення. Це дозволяє використовувати в додатках бази даних, де втрата даних не є можливою.
strattonn

Linux зберігає дані, ще не записані в оперативній пам'яті, а не на жорсткому диску. У жорсткого диска теж є власний кеш.
Барафу Альбіно

Було б досить зручно, якщо будь-який файл, відкритий процесом, буде синхронізовано, коли процес закриється. Це не вплине на сам процес, але спростить сценарії оболонки тощо (які тепер мають синхронізувати цілу файлову систему)
MSalters

14
Це більше, ніж ілюзія. Асинхронні записи покращують загальну продуктивність додатків.
jlliagre

4
@frostschutz: Крім файлів, які існують лише тимчасово, також існує факт, що деякі області файлів перезаписуються знову і знову.
Матьє М.

26

Асинхронний, буферний введення / вивід використовувався до Linux і навіть перед Unix. У Unix це було, і так є всі його наслідки.

Ось що написали Річі та Томпсон у своєму документі CACM - Система розподілу часу UNIX :

Користувачеві і читання, і запис файлів здаються синхронними та небуферованими. Це відразу після повернення з виклику зчитування, дані доступні, і навпаки, після запису робоча область користувача може бути повторно використана. Насправді система підтримує досить складний буферний механізм, який значно скорочує кількість операцій вводу / виводу, необхідних для доступу до файлу.


У своєму запитанні ви також написали:

Чи немає небезпеки, що запис вийде з ладу через помилку вводу-виводу?

Так, запис може не вдатися, і програма може ніколи про це не знати. Хоча ніколи не добре, наслідки цього можна мінімізувати у випадках, коли помилка вводу / виводу породжує системну паніку (на деяких ОС це налаштовується - замість паніки система може продовжувати працювати, але постраждала файлова система є демонтований або встановлений лише для читання). Потім користувачі можуть отримувати повідомлення про те, що дані у цій файловій системі є підозрюваними. А дисковий накопичувач може проактивно моніторитись, щоб побачити, чи швидко зростає його список дефектів , що є свідченням того, що накопичувач виходить з ладу.

BSD додав fsyncсистемний виклик, щоб програма могла бути впевнена, що його файлові дані були повністю записані на диск перед тим, як продовжити, а наступні системи Unix надали можливість робити синхронні записи. GNU dd має можливість conv=fsyncпереконатися, що всі дані були списані до завершення команди. Це стане в нагоді під час запису на повільні знімні флешки, де завантажені дані можуть зайняти кілька хвилин.

Іншим джерелом пошкодження файлів є раптове відключення системи, наприклад від втрати живлення. Практично всі поточні системи підтримують чистий / брудний прапор у своїх файлових системах. Прапор встановлюється чистим, коли більше даних не потрібно записувати, а файлова система збирається відключити, як правило, під час відключення системи або за допомогою виклику вручну umount. Системи зазвичай працюватимуть fsckпри перезавантаженні, якщо виявлять, що файлові системи не були закриті чисто.


Припустимо, ми копіюємо музику з жорсткого диска на зовнішній диск. Може статися, що зовнішній накопичувач пошкоджений і запис вийде з ладу. Це не призведе до запуску програми з помилковими даними. І, здається, зайвим буде панікувати невдалий IO на зовнішньому пристрої.
marmistrz

Влучне зауваження. Я модифікую свою відповідь.
Марк Плотнік

15

Багато хороших відповідей, але дозвольте додати ще одне: Пам'ятайте, що Unix - це багатопроцесова та багатокористувацька система, тому потенційно багато користувачів намагаються робити файлові операції (наприклад, пише) на (майже) той же час. Зі старими повільними жорсткими дисками - можливо, встановленими через мережу - це не тільки потребуватиме часу (для чого програми в основному замикаються, і користувачі повинні чекати), але й спричинять багато рухомих головок читання / запису диск вперед і назад.

Отже, натомість файли, які очікують на запис, деякий час зберігалися в пам’яті та сортувалися за тим, де вони повинні опинитися на диску… і коли буфер був заповнений - або демон, що синхронізував диск, чекав на потрібна кількість секунд (я думаю, це було зазвичай близько 30 секунд) - весь буфер виписувався на диск "по порядку", при цьому головці для запису потрібно було робити один нескінченний рух, записуючи файли на диск як пішло ... замість того, щоб стрибати всюди.

З урахуванням сучасних швидких дисків - не кажучи вже про твердотілих пристроях - виграш набагато менший ... особливо в домашній linux-системі, де одночасно працює лише один користувач, і лише з кількома програмами.

У будь-якому випадку, комбінація очікування читання, читаючи в (до кеша / буфера) більше, ніж просили, - і сортування даних, які чекають, щоб їх було записано, щоб вони могли бути записані "одним рухом" - насправді була дуже хорошою ідеєю в час, особливо в системах з великою кількістю читання та запису багатьма користувачами.


2
XFS навіть не вирішує, куди зберігати дані до моменту виписки. Затримка-розподіл дає алокатору набагато більше інформації, на якій базуються свої рішення. Коли файл вперше записується, немає ніякого способу дізнатися, чи буде це файл 4k або файл 1G та ще зростаючий файл. Якщо десь є 10G суміжного вільного місця, розміщення файлу 4k на початку не принесе користі. Поміщення великого файлу на початку великого вільного простору зменшує фрагментацію.
Пітер Кордес

13

Він не специфічний для Linux, і він називається кеш сторінок (що Linux цілком добре). Дивіться також http://linuxatemyram.com/ ; тож якщо файл записаний, то прочитайте ще раз через кілька секунд, дуже часто дискові введення-виведення не потрібні.

Основна перевага полягає в тому, що в багатьох системах є багато оперативної пам’яті, а частина її може використовуватись як кеш ядра. Так деякі операції з файлами можуть отримати користь від цього кешування. Крім того, час вводу / виводу диска набагато повільніше (зазвичай це багато тисяч разів для SDD і майже мільйон разів повільніше для механічних жорстких дисків), ніж оперативна пам'ять.

Код програми може дати підказки щодо цього кешування: див., Наприклад, posix_fadvise (2) та madvise (2)


8

Спінінг-плати повільніше, ніж оперативна пам'ять. Ми використовуємо кешування прочитаних / записів, щоб "приховати" цей факт.

Корисна річ у записі IO полягає в тому, що вона не вимагає, щоб IO диска відбувався негайно - на відміну від читання, де ви не можете повернути дані користувачеві, поки зчитування не завершиться на диску.

Таким чином, записи працюють в умовах обмеженого часового обмеження - до тих пір, поки наша стабільна пропускна здатність не перевищує показника нашого диска, ми можемо приховати велику кількість покарань за продуктивність у кеш-пам'яті запису.

І нам потрібно писати кеш - спінінг-диски дуже повільні порівняно. Але для сучасних типів RAID передбачено суттєве покарання за роботу.

Наприклад, RAID 6, щоб завершити один запис IO, повинен:

  • Прочитайте блок оновлення
  • читати паритет1
  • читати паритет 2
  • написати новий блок
  • написати парність 1
  • написати парність 2

Таким чином, кожне записування насправді становить 6 операцій вводу-виводу - особливо коли у вас повільні диски, як великі диски SATA, це стає надзвичайно дорогим.

Але є приємне просте рішення - писати спільно. Якщо ви можете створити "повну смужку" запису в буфері, вам не потрібно читати паритет з диска - ви можете обчислити його, виходячи з того, що у вас є в пам'яті.

Це дуже бажано робити, тому що тоді у вас більше немає посилення запису. Дійсно, ви можете отримати менший штраф, ніж RAID 1 + 0.

Поміркуйте:

RAID 6, 8 + 2 - 10 шпинделів.

8 послідовних блоків даних для запису - обчисліть паритет у кеші і запишіть один блок на кожен диск. 10 пише за 8, означає штраф за 1,25. На 10 дисках RAID 1 + 0 все ще передбачено покарання 2 (тому що ви повинні писати до кожного субмістра). Тож у цьому сценарії ви дійсно можете змусити RAID 6 працювати краще, ніж RAID1 + 0. У реальному використанні ви хочете отримати трохи більше змішаного профілю вводу-виводу.

Таким чином, кешування записів має величезну різницю для сприйнятої продуктивності наборів RAID - ви можете писати зі швидкістю оперативної пам’яті та маєте низьке покарання для запису - покращуючи стабільну пропускну здатність, якщо ви це зробите.

Якщо ви цього не зробите, ви страждаєте від повільної продуктивності SATA, але помножте її на 6 і додайте до неї певну суперечку. Ваш 10-ти сторонній SATA RAID-6 без кешування записів був би трохи швидшим, ніж один диск без RAID ... але не дуже.

Ви все ж ризикуєте - як зазначаєте - втрата електроенергії означає втрату даних. Ви можете пом'якшити це за допомогою циклів промивання кеш-пам'яті, резервного копіювання батареї кеш-пам'яті або використання SSD або інших енергонезалежних кешів.


7

Жодна з інших відповідей не згадувала про затримку виділення . Усі XFS, ext4, BTRFS і ZFS використовують його. XFS використовує його ще до існування ext4, тому я буду використовувати його як приклад:

XFS навіть не вирішує, куди зберігати дані до моменту виписки. Затримка-розподіл дає алокатору набагато більше інформації, на якій базуються свої рішення. Коли файл вперше записується, немає ніякого способу дізнатися, чи буде це файл 4k або файл 1G та ще зростаючий файл. Якщо десь є 10G суміжного вільного місця, розміщення файлу 4k на початку не принесе користі. Поміщення великого файлу на початку великого вільного простору зменшує фрагментацію.


4

Всі інші відповіді тут, як мінімум, в основному правильні для звичайного випадку, і я рекомендую прочитати будь-який з них до мого, але ви згадали, що DD і dd має типовий випадок використання, який може не включати кешування запису. Кешування записів реалізується насамперед на рівні файлової системи. Сирі пристрої зазвичай не кешують запис (кілька драйверів пристроїв, такі як raid або lvm, - це ще одна кулька воску). Оскільки DD часто використовується з необмеженими блоковими пристроями, він надає bs та пов'язані з ними варіанти, щоб дозволити великі записи для кращої роботи на сировинних пристроях. Це не так корисно, коли обидві кінцеві точки є звичайними файлами (хоча великі записи в цьому випадку використовують менше системних викликів). Інше поширене місце, де це особливо помітно, - це пакет mtools, який є реалізацією файлової системи жирового простору користувача. використання mtools з дискетою завжди відчуває себе дуже мляво, оскільки інструменти повністю синхронні, а дискети надзвичайно повільні. Монтаж дискети та використання файлової системи ядра жиру набагато більш чуйний, за винятком синхронного уманту (і для нього дуже важливо таким чином запобігти втраті даних, особливо для знімних пристроїв, таких як дискети). Є лише кілька інших програм, які я знаю, що регулярно використовуюсь із необробленими пристроями, такими як спеціально налаштовані бази даних (які реалізують власне кешування запису), tar та спеціальні засоби та файлові системи, такі як chdsk, mkfs та mt. Монтаж дискети та використання файлової системи ядра жиру набагато більш чуйний, за винятком синхронного уманту (і для нього дуже важливо таким чином запобігти втраті даних, особливо для знімних пристроїв, таких як дискети). Є лише кілька інших програм, які я знаю, що регулярно використовуюсь із необробленими пристроями, такими як спеціально налаштовані бази даних (які реалізують власне кешування запису), tar та спеціальні засоби та файлові системи, такі як chdsk, mkfs та mt. Монтаж дискети та використання файлової системи ядра жиру набагато більш чуйний, за винятком синхронного уманту (і для нього дуже важливо таким чином запобігти втраті даних, особливо для знімних пристроїв, таких як дискети). Є лише кілька інших програм, які я знаю, що регулярно використовуюсь із необробленими пристроями, такими як спеціально налаштовані бази даних (які реалізують власне кешування запису), tar та спеціальні засоби та файлові системи, такі як chdsk, mkfs та mt.


4
Linux блокові пристрої читають / записують кеш сторінки за замовчуванням. Ви повинні використовувати, O_DIRECTякщо ви хочете обійти кеш. dd oflag=direct. IIRC, деякі варіанти за замовчуванням спрямовують введення / виведення на блокові пристрої. (І вимагають читання / написання вирівняних блоків, чого Linux не має, тому що все-таки просто записує кеш сторінки.)
Пітер Кордес,

3

Філософія небезпечна за замовчуванням.

Можливі дві розумні і очевидні стратегії: негайно записувати запис на диск або затягувати запис. UNIX історично обрала останнє. Тож для забезпечення безпеки вам потрібно зателефонувати fsyncпісля цього.

Однак ви можете вказати безпеку наперед, встановивши пристрій з опцією syncабо на файл, відкривши їх O_SYNC.

Пам'ятайте, що UNIX був розроблений для комп'ютерних експертів. "Безпечний за замовчуванням" не вважався. Безпека означає повільніший введення / виведення, і ті ранні системи дійсно мали повільний введення / виведення, що підвищувало швидкість ціни. На жаль, ні UNIX, ні Linux не перейшли на безпечний режим за замовчуванням, навіть якщо це неперервна зміна.


6
Дуже велика більшість додатків і користувачів не потребують і не дбають про безпеку, яку забезпечували б синхронні записи. Якщо стався збій або відключення електроенергії, ви ризикуєте втратити дані за останні 30 секунд. Це добре з більшістю людей, якщо немає фінансової операції чи чогось подібного, що коштуватиме більше 30 секунд нашого часу. Неприйняття синхронного вводу / виводу означало б, що всі програми, орієнтовані на зручність використання, мали б визначити O_NOSYNC.
jlliagre

2

Він торгує невеликою кількістю надійності для значного збільшення пропускної здатності.

Припустимо, наприклад, програму для стиснення відео. З затримкою запису ("записувати назад"):

  1. витратити 10 мс на стискання кадру
  2. видати кадр запису на диск
  3. зачекайте 10 мс, щоб диск підтвердив, що запис завершено
  4. ГОТО 1

Проти

  1. витратити 10 мс на стискання кадру
  2. випустити кадр запису на диск (завершує у фоновому режимі)
  3. ГОТО 1

Друга версія з'являється вдвічі швидше, оскільки вона може одночасно використовувати процесор і диск, тоді як перша версія завжди чекає тієї чи іншої.

Зазвичай ви хочете списання для потокових операцій та операцій з масовими файлами, а також для баз даних та додатків, схожих на базу даних.


1

У багатьох додатках пристрої зберігання даних будуть перериваються з читанням даних. Якщо система завжди здатна відкладати запис до моменту, коли запам'ятовуючий пристрій не зайнятий зчитуванням даних, то, з точки зору програми, записування займе нульовий час для завершення. Єдиними ситуаціями, в яких письмо не було б миттєвим, було б, коли:

  1. Буфери для запису заповнюють до того, що більше не можна приймати запити відкладеного запису, поки запис фактично не завершиться.

  2. Потрібно вимкнути або вийняти пристрій, про який очікують записи.

  3. Програма спеціально вимагає підтвердження того, що запис фактично завершено.

Справді, це лише тому, що вищезазначені вимоги взагалі повинні взагалі мати місце. З іншого боку, взагалі немає причин не виконувати жодних відкладених записів у моменти, коли пристрій в іншому випадку не працює, тому багато систем виконує їх тоді.


0

Є також таке:

Пишіть "Привіт, Джо Мо"
швидше, ніж:
Напишіть "Привіт",
Напишіть "Джо"
Напишіть "Мо"

І також:

Напишіть "Привіт, як справи?"
швидше, ніж:
Напишіть "Привіт, що там?"
Видаліть
написання "Howdy, як ти?"
Видаліть
написання "Привіт, як справи?"

Краще, щоб модифікації та агрегація відбувалися в оперативній пам'яті, ніж на диску. Пакетний диск записує розробників додатків від таких проблем.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.