වලාකුළු පද්ධතිවල දත්ත ගබඩා කිරීමේ තිරසාරභාවය පිළිබඳ පර්යේෂණ කරන අතරතුර, මම මූලික දේවල් තේරුම් ගෙන ඇති බව සහතික කර ගැනීමට මා පරීක්ෂා කිරීමට තීරණය කළෙමි. මම
මෙම සටහනේදී, මම Linux ගොනු API මඟින් සපයන ස්ථීර ගබඩා යාන්ත්රණයන් ගවේෂණය කරමි. මෙහි සෑම දෙයක්ම සරල විය යුතු බව පෙනේ: වැඩසටහන විධානය අමතන්න write()
, සහ මෙම විධානය අවසන් වූ පසු, දත්ත ආරක්ෂිතව තැටියට සුරකිනු ඇත. එහෙත් write()
RAM හි ඇති කර්නල් හැඹිලියට පමණක් යෙදුම් දත්ත පිටපත් කරයි. තැටියට දත්ත ලිවීමට පද්ධතියට බල කිරීම සඳහා, ඔබට අමතර යාන්ත්රණ කිහිපයක් භාවිතා කිරීමට අවශ්ය වේ.
සමස්තයක් වශයෙන්, මෙම ද්රව්යය මට උනන්දුවක් දක්වන මාතෘකාවක් පිළිබඳව මා ඉගෙන ගත් දේට අදාළ සටහන් එකතුවකි. අපි වැදගත්ම දේ ගැන ඉතා කෙටියෙන් කතා කරන්නේ නම්, තිරසාර දත්ත ගබඩා කිරීම සංවිධානය කිරීම සඳහා ඔබ විධානය භාවිතා කළ යුතු බව පෙනේ. fdatasync()
හෝ ධජය සමඟ ගොනු විවෘත කරන්න O_DSYNC
. කේතයේ සිට තැටිය දක්වා දත්ත වලට සිදුවන්නේ කුමක්ද යන්න ගැන වැඩිදුර ඉගෙන ගැනීමට ඔබ කැමති නම්, බලන්න
ලිවීම () ශ්රිතය භාවිතා කිරීමේ විශේෂාංග
පද්ධති ඇමතුම write()
සම්මතයේ අර්ථ දක්වා ඇත write()
දත්ත කියවීමේ මෙහෙයුම් මගින් කලින් ලියා ඇති බයිට් හරියටම ආපසු ලබා දිය යුතුය, දත්ත වෙනත් ක්රියාවලි හෝ නූල් වලින් ප්රවේශ වුව ද මෙය සිදු කරයි (
මෙයින් අදහස් කරන්නේ මෙහෙයුම බවයි write()
එය පරමාණුක ද? තාක්ෂණික දෘෂ්ටි කෝණයකින්, ඔව්. දත්ත කියවීමේ මෙහෙයුම් ලියා ඇති දේ සියල්ල හෝ කිසිවක් ආපසු ලබා දිය යුතුය write()
. නමුත් මෙහෙයුම write()
, සම්මතයට අනුව, එය ලිවීමට ඉල්ලා සිටි සියල්ල ලිවීමෙන් අවසන් කළ යුතු නොවේ. දත්ත වලින් කොටසක් පමණක් ලිවීමට ඇයට අවසර ඇත. උදාහරණයක් ලෙස, එකම ගොනු විස්තරය මගින් විස්තර කර ඇති ගොනුවකට බයිට් 1024ක් එක් කරන නූල් දෙකක් අපට තිබිය හැක. සම්මතයේ දෘෂ්ටි කෝණයෙන්, පිළිගත හැකි ප්රතිඵලය වනුයේ එක් එක් ලිවීමේ මෙහෙයුම ගොනුවට එක් බයිටයක් පමණක් එකතු කළ හැකි විටය. මෙම මෙහෙයුම් පරමාණුකව පවතිනු ඇත, නමුත් ඒවා සම්පූර්ණ වූ පසු, ඔවුන් ගොනුවට ලියූ දත්ත මිශ්ර වේ.
fsync() සහ fdatasync() ශ්රිත
තැටියට දත්ත ෆ්ලෂ් කිරීමට පහසුම ක්රමය වන්නේ කාර්යය ඇමතීමයි fdatasync()
. මෙම fdatasync()
මෙම ශ්රිතයේ ක්රියාකාරිත්වය අතරතුර, එවැනි පාර-දත්ත ප්රමාණයක් තැටියට සුරකින අතර එය “පහත සඳහන් දත්ත කියවීමේ මෙහෙයුම් නිවැරදිව ක්රියාත්මක කිරීම සඳහා අවශ්ය” බව කියනු ලැබේ. බොහෝ යෙදුම් සැලකිලිමත් වන්නේ මෙයයි.
මෙහිදී මතුවිය හැකි එක් ගැටලුවක් නම්, මෙම යාන්ත්රණය මඟින් සිදුවිය හැකි අසාර්ථකත්වයකින් පසුව ගොනුව සොයා ගත හැකි බවට සහතික නොවීමයි. විශේෂයෙන්ම, නව ගොනුවක් නිර්මාණය කිරීමේදී, ඔබ ඇමතීමට අවශ්ය වේ fsync()
එය අඩංගු නාමාවලිය සඳහා. එසේ නොමැතිනම්, අසාර්ථක වීමෙන් පසුව, මෙම ගොනුව නොපවතින බව පෙනී යා හැක. මෙයට හේතුව වන්නේ UNIX හි දෘඪ සබැඳි භාවිතය හේතුවෙන් ගොනුවක් නාමාවලි කිහිපයක පැවතිය හැකි වීමයි. එබැවින්, ඇමතීමේදී fsync()
කුමන ඩිරෙක්ටරි දත්ත ද තැටියට ෆ්ලෂ් කළ යුතුදැයි දැන ගැනීමට ගොනුවකට ක්රමයක් නොමැත (fsync()
අනුරූප ගොනු අඩංගු නාමාවලි වෙත, නමුත් මෙය අනෙකුත් ගොනු පද්ධති සමඟ සිදු නොවිය හැක.
මෙම යාන්ත්රණය විවිධ ගොනු පද්ධති මත වෙනස් ලෙස ක්රියාත්මක විය හැක. මම පාවිච්චි කළා fdatasync()
ටිකක් වේගවත් fsync()
. උපයෝගිතා blktrace
බව පෙන්නුම් කරයි fdatasync()
සාමාන්යයෙන් අඩු දත්ත තැටියට ලියයි (ext4 හි fsync()
20 KiB ලියයි, සහ fdatasync()
- 16 KiB). ඒ වගේම XFS ext4 වලට වඩා ටිකක් වේගවත් බව මට දැනගන්නට ලැබුණා. සහ මෙහි උපකාරයෙන් blktrace
බව සොයා ගැනීමට සමත් විය fdatasync()
අඩු දත්ත තැටියට ෆ්ලෂ් කරයි (XFS හි 4 KiB).
fsync() භාවිතා කරන විට ඇතිවන නොපැහැදිලි තත්වයන්
මට අපැහැදිලි අවස්ථා තුනක් ගැන සිතිය හැකිය fsync()
මම ප්රායෝගිකව මුහුණ දුන්.
එවැනි පළමු නඩුව 2008 දී සිදු විය. එවිට ගොනු විශාල ප්රමාණයක් තැටියට ලියා ඇත්නම් Firefox 3 අතුරුමුහුණත කැටි විය. ගැටළුව වූයේ අතුරු මුහුණත ක්රියාත්මක කිරීම එහි තත්වය පිළිබඳ තොරතුරු ගබඩා කිරීම සඳහා SQLite දත්ත ගබඩාවක් භාවිතා කිරීමයි. අතුරු මුහුණතේ සිදු වූ එක් එක් වෙනස් වීමෙන් පසුව, ශ්රිතය කැඳවනු ලැබීය fsync()
, ස්ථාවර දත්ත ගබඩා කිරීම සඳහා හොඳ සහතිකයක් ලබා දුන්නේය. පසුව භාවිතා කරන ලද ext3 ගොනු පද්ධතියේ, ශ්රිතය fsync()
පද්ධතියේ ඇති සියලුම "අපිරිසිදු" පිටු තැටියට දමා, අනුරූප ගොනුවට සම්බන්ධ ඒවා පමණක් නොවේ. මෙයින් අදහස් කළේ ෆයර්ෆොක්ස් හි බොත්තමක් ක්ලික් කිරීමෙන් චුම්බක තැටියකට මෙගාබයිට් දත්ත ලිවිය හැකි අතර එය තත්පර ගණනාවක් ගත විය හැකි බවයි. ගැටලුවට විසඳුම, මා තේරුම් ගත් පරිදි
දෙවන ගැටලුව 2009 දී ඇති විය. ඉන්පසුව, පද්ධති බිඳවැටීමකින් පසුව, නව ext4 ගොනු පද්ධතිය භාවිතා කරන්නන් අලුතින් සාදන ලද බොහෝ ගොනු වල දිග ශුන්ය වූ නමුත් පැරණි ext3 ගොනු පද්ධතිය සමඟ මෙය සිදු නොවීය. කලින් ඡේදයේ, මම ext3 තැටියට වැඩිපුර දත්ත ෆ්ලෂ් කළ ආකාරය ගැන කතා කළෙමි, එමඟින් දේවල් බොහෝ සෙමින් අඩු විය. fsync()
. තත්වය වැඩිදියුණු කිරීම සඳහා, ext4 හි විශේෂිත ගොනුවකට අදාළ වන අපිරිසිදු පිටු පමණක් තැටියට ෆ්ලෂ් කරනු ලැබේ. තවද අනෙකුත් ගොනු වල දත්ත ext3 සමඟ වඩා දිගු කාලයක් මතකයේ පවතී. මෙය කාර්ය සාධනය වැඩි දියුණු කිරීම සඳහා සිදු කරන ලදී (පෙරනිමියෙන්, දත්ත තත්පර 30 ක් මෙම තත්වයේ පවතී, ඔබට මෙය වින්යාසගත කළ හැක fsync()
ස්ථාවර දත්ත ගබඩා කිරීම සහතික කිරීමට සහ අසාර්ථකත්වයේ ප්රතිවිපාකවලින් හැකිතාක් ඒවා ආරක්ෂා කිරීමට අවශ්ය යෙදුම්වල. කාර්යය fsync()
ext4 භාවිතා කරන විට වඩා ext3 භාවිතා කරන විට වඩා කාර්යක්ෂමව ක්රියා කරයි. මෙම ප්රවේශයේ අවාසිය නම්, එහි භාවිතය, පෙර මෙන්, වැඩසටහන් ස්ථාපනය කිරීම වැනි සමහර මෙහෙයුම් ක්රියාත්මක කිරීම මන්දගාමී වේ. මේ ගැන විස්තර බලන්න
සම්බන්ධ තුන්වන ගැටලුව fsync()
, 2018 දී ආරම්භ විය. පසුව, PostgreSQL ව්යාපෘතියේ රාමුව තුළ, එය ශ්රිතය නම් බව සොයා ගන්නා ලදී fsync()
දෝෂයක් හමු වේ, එය "අපිරිසිදු" පිටු "පිරිසිදු" ලෙස සලකුණු කරයි. ප්රතිඵලයක් වශයෙන්, පහත සඳහන් ඇමතුම් fsync()
ඔවුන් එවැනි පිටු සමඟ කිසිවක් නොකරයි. මේ නිසා, වෙනස් කරන ලද පිටු මතකයේ ගබඩා කර ඇති අතර කිසි විටෙකත් තැටියට ලියා නොමැත. මෙය සැබෑ ව්යසනයකි, මන්ද යෙදුම සමහර දත්ත තැටියට ලියා ඇති බව සිතනු ඇත, නමුත් ඇත්ත වශයෙන්ම එය එසේ නොවේ. එවැනි අසාර්ථකත්වයන් fsync()
දුර්ලභ ය, එවැනි අවස්ථාවන්හිදී යෙදුමට ගැටලුව සමඟ සටන් කිරීමට කිසිවක් කළ නොහැක. මේ දිනවල, මෙය සිදු වූ විට, PostgreSQL සහ අනෙකුත් යෙදුම් බිඳ වැටේ. O_SYNC
හෝ කොඩියක් සමඟ O_DSYNC
. මෙම ප්රවේශය සමඟ, පද්ධතිය නිශ්චිත ලිවීමේ මෙහෙයුම් වලදී සිදුවිය හැකි දෝෂ වාර්තා කරනු ඇත, නමුත් මෙම ප්රවේශය සඳහා යෙදුමට බෆර කළමනාකරණය කිරීමට අවශ්ය වේ. මේ ගැන වැඩිදුර කියවන්න
O_SYNC සහ O_DSYNC ධජ භාවිතයෙන් ගොනු විවෘත කිරීම
ස්ථාවර දත්ත ගබඩාවක් සපයන ලිනක්ස් යාන්ත්රණ පිළිබඳ සාකච්ඡාවට නැවත යමු. එනම්, අපි කොඩිය භාවිතා කිරීම ගැන කතා කරමු O_SYNC
හෝ කොඩිය O_DSYNC
පද්ධති ඇමතුම භාවිතයෙන් ගොනු විවෘත කරන විට write()
පද්ධතියට ඒ අනුව විධාන ලබා දේ fsync()
и fdatasync()
. මෙම write()
и fdatasync()
) මෙම ප්රවේශයේ ප්රධාන අවාසිය නම්, අදාළ ගොනු විස්තරය භාවිතා කරන සියලුම ලිවීම් සමමුහුර්ත වන අතර එමඟින් යෙදුම් කේතය ව්යුහගත කිරීමේ හැකියාව සීමා කළ හැකිය.
O_DIRECT ධජය සමඟ සෘජු I/O භාවිතා කිරීම
පද්ධති ඇමතුම open()
ධජයට සහය දක්වයි O_DIRECT
, තැටිය සමඟ සෘජුව අන්තර්ක්රියා කිරීමෙන් I/O මෙහෙයුම් සිදු කිරීම සඳහා මෙහෙයුම් පද්ධති හැඹිලිය මඟ හැරීමට සැලසුම් කර ඇත. මෙය බොහෝ අවස්ථාවලදී, වැඩසටහන මඟින් නිකුත් කරන ලද ලිවීමේ විධාන තැටිය සමඟ වැඩ කිරීම ඉලක්ක කරගත් විධානයන් බවට සෘජුවම පරිවර්තනය කරනු ඇත. නමුත්, සාමාන්යයෙන්, මෙම යාන්ත්රණය කාර්යයන් සඳහා ආදේශකයක් නොවේ fsync()
හෝ fdatasync()
. කාරණය වන්නේ තැටියටම හැකි බවයි O_DIRECT
, O_DSYNC
, එයින් අදහස් වන්නේ එක් එක් ලිවීමේ මෙහෙයුම ඇමතුමක් මගින් අනුගමනය කරනු ඇති බවයි fdatasync()
.
XFS ගොනු පද්ධතිය මෑතකදී "වේගවත් මාර්ගයක්" එකතු කර ඇති බව පෙනී ගියේය O_DIRECT|O_DSYNC
- දත්ත පටිගත කිරීම. බ්ලොක් එකක් නැවත ලියන්නේ නම් O_DIRECT|O_DSYNC
, එවිට XFS, හැඹිලිය ෆ්ලෂ් කිරීම වෙනුවට, උපාංගය එයට සහය දක්වන්නේ නම් FUA ලිවීමේ විධානය ක්රියාත්මක කරයි. මම මෙය උපයෝගිතා භාවිතයෙන් තහවුරු කළෙමි blktrace
Linux 5.4/Ubuntu 20.04 පද්ධතියක් මත. මෙම ප්රවේශය වඩාත් කාර්යක්ෂම විය යුතුය, මන්ද භාවිතා කරන විට අවම දත්ත ප්රමාණයක් තැටියට ලියා ඇති අතර එක් මෙහෙයුමක් භාවිතා කරනු ලැබේ, දෙකකට වඩා (හැඹිලිය ලිවීම සහ ෆ්ලෂ් කිරීම). මට සබැඳියක් හමු විය
sync_file_range() ශ්රිතය
Linux හි පද්ධති ඇමතුමක් ඇත sync_file_range()
කණ්ඩායම "ඉතා භයානක" යැයි කියනු ලැබේ. එය භාවිතා කිරීම නිර්දේශ නොකරයි. විශේෂාංග සහ අන්තරායන් sync_file_range()
ඉතා හොඳින් විස්තර කර ඇත fdatasync()
. මෙම sync_file_range()
ZFS භාවිතා කරන විට, එය තැටියට දත්ත ෆ්ලෂ් නොකරයි. අත්දැකීමෙන් මට කියන්නේ කලාතුරකින් භාවිතා වන කේතය දෝෂ අඩංගු වීමට ඉඩ ඇති බවයි. එබැවින්, අත්යවශ්ය නම් මිස මෙම පද්ධති ඇමතුම භාවිතා කිරීමට එරෙහිව මම උපදෙස් දෙමි.
දත්ත පැවැත්ම සහතික කිරීමට උපකාර වන පද්ධති ඇමතුම්
දත්ත අඛණ්ඩතාව සහතික කරන I/O මෙහෙයුම් සිදු කිරීමට භාවිතා කළ හැකි ප්රවේශයන් තුනක් ඇති බව මම නිගමනය කර ඇත්තෙමි. ඔවුන් සියල්ලටම ක්රියාකාරී ඇමතුමක් අවශ්ය වේ fsync()
ගොනුව නිර්මාණය කරන ලද නාමාවලිය සඳහා. මෙම ප්රවේශයන් වේ:
- කාර්යයක් ඇමතීම
fdatasync()
හෝfsync()
කාර්යයෙන් පසුවwrite()
(එය භාවිතා කිරීම වඩා හොඳයfdatasync()
). - ධජයක් සමඟ විවෘත කරන ලද ගොනු විස්තරයක් සමඟ වැඩ කිරීම
O_DSYNC
හෝO_SYNC
(වඩා හොඳ - කොඩියක් සමඟO_DSYNC
). - විධානය භාවිතා කිරීම
pwritev2()
කොඩිය සමඟRWF_DSYNC
හෝRWF_SYNC
(වඩාත් සුදුසු කොඩියක් සමඟRWF_DSYNC
).
කාර්ය සාධන සටහන්
මා විසින් පරීක්ෂා කරන ලද විවිධ යාන්ත්රණවල ක්රියාකාරීත්වය මම පරෙස්සමින් මනින්නේ නැත. ඔවුන්ගේ කාර්යයේ වේගයේ මා දුටු වෙනස්කම් ඉතා කුඩා ය. මෙයින් අදහස් කරන්නේ මා වැරදි විය හැකි බවත්, විවිධ තත්වයන් යටතේ එකම දෙය විවිධ ප්රතිඵල ඇති කළ හැකි බවත්ය. පළමුව, මම කාර්ය සාධනයට වැඩිපුර බලපාන දේ ගැන කතා කරමි, පසුව කාර්ය සාධනයට අඩුවෙන් බලපාන දේ.
- ගොනු දත්ත නැවත ලිවීම ගොනුවකට දත්ත එක් කිරීමට වඩා වේගවත් වේ (කාර්ය සාධන ප්රතිලාභය 2-100% විය හැක). ගොනුවකට දත්ත එක් කිරීමට පද්ධති ඇමතුමකින් පසුව පවා ගොනුවේ පාරදත්ත වෙත අමතර වෙනස්කම් අවශ්ය වේ
fallocate()
, නමුත් මෙම බලපෑමේ විශාලත්වය වෙනස් විය හැක. හොඳම කාර්ය සාධනය සඳහා, ඇමතීමට මම නිර්දේශ කරමිfallocate()
අවශ්ය ඉඩ කලින් වෙන් කිරීමට. එවිට මෙම අවකාශය පැහැදිලිවම ශුන්ය වලින් පුරවා කැඳවිය යුතුයfsync()
. ගොනු පද්ධතියේ අනුරූප බ්ලොක් "නොකැඩී" වෙනුවට "වෙන් කළ" ලෙස සලකුණු කර ඇති බව මෙය සහතික කරයි. මෙය කුඩා (2% ක් පමණ) කාර්ය සාධන වැඩිදියුණු කිරීමක් ලබා දෙයි. මීට අමතරව, සමහර තැටි අනෙක් ඒවාට වඩා බ්ලොක් එකකට පළමු ප්රවේශය මන්දගාමී විය හැක. මෙයින් අදහස් කරන්නේ ශුන්ය වලින් අවකාශය පිරවීමෙන් කාර්ය සාධනයේ සැලකිය යුතු (100% ක් පමණ) දියුණුවක් ඇති විය හැකි බවයි. විශේෂයෙන්ම, මෙය තැටි සමඟ සිදු විය හැකAWS EBS (මෙය නිල නොවන දත්ත, මට එය තහවුරු කළ නොහැකි විය). ගබඩා කිරීම සඳහා ද එය එසේම වේGCP Persistent Disk (මෙය දැනටමත් නිල තොරතුරු, පරීක්ෂණ මගින් තහවුරු කර ඇත). අනෙකුත් විශේෂඥයින් ද එයම කර ඇතනිරීක්ෂණ , විවිධ තැටි සම්බන්ධ. - පද්ධති ඇමතුම් අඩු වන තරමට කාර්ය සාධනය වැඩි වේ (ලාභ 5% පමණ විය හැක). අභියෝගයක් වගේ
open()
කොඩිය සමඟO_DSYNC
හෝ අමතන්නpwritev2()
කොඩිය සමඟRWF_SYNC
ඇමතුමකට වඩා වේගවත්fdatasync()
. එකම ගැටළුව විසඳීමට (එක ඇමතුමක් වෙනුවට එක් ඇමතුමක්) අඩු පද්ධති ඇමතුම් ප්රමාණයක් සිදු කළ යුතු බවට මෙම ප්රවේශය කාර්යභාරයක් ඉටු කරන බව මම සැක කරමි. නමුත් කාර්ය සාධනයේ වෙනස ඉතා කුඩා වේ, එබැවින් ඔබට එය සම්පූර්ණයෙන්ම නොසලකා හැර එහි තර්කනය සංකීර්ණ නොවන යෙදුමේ යමක් භාවිතා කළ හැකිය.
ඔබ තිරසාර දත්ත ගබඩා කිරීමේ මාතෘකාව ගැන උනන්දුවක් දක්වන්නේ නම්, මෙන්න ප්රයෝජනවත් ද්රව්ය කිහිපයක්:
I/O ප්රවේශ ක්රම - ආදාන/ප්රතිදාන යාන්ත්රණවල මූලික කරුණු පිළිබඳ දළ විශ්ලේෂණය.දත්ත තැටිය වෙත ළඟා වීම සහතික කිරීම — යෙදුමේ සිට තැටියට යන ගමනේදී දත්ත වලට සිදුවන්නේ කුමක්ද යන්න පිළිබඳ කතාවකි.ඔබ අඩංගු බහලුම fsync කළ යුත්තේ කවදාද? - භාවිතා කළ යුත්තේ කවදාද යන ප්රශ්නයට පිළිතුරfsync()
නාමාවලි සඳහා. මෙය කෙටියෙන් කිවහොත්, නව ගොනුවක් සෑදීමේදී ඔබ මෙය කළ යුතු බව පෙනී යන අතර, මෙම නිර්දේශයට හේතුව ලිනක්ස් හි එකම ගොනුව සඳහා බොහෝ යොමු කිරීම් තිබිය හැකිය.ලිනක්ස් හි SQL සේවාදායකය: FUA අභ්යන්තර — Linux වේදිකාවේ SQL Server තුළ ස්ථීර දත්ත ගබඩා කිරීම ක්රියාත්මක කරන ආකාරය පිළිබඳ විස්තරයක් මෙන්න. මෙහි Windows සහ Linux පද්ධති ඇමතුම් අතර රසවත් සැසඳීම් කිහිපයක් තිබේ. XFS හි FUA ප්රශස්තකරණය ගැන මම ඉගෙන ගත්තේ මෙම ද්රව්යයට ස්තූතිවන්ත වන බව මට බොහෝ දුරට විශ්වාසයි.
තැටියක ආරක්ෂිතව ගබඩා කර ඇතැයි ඔබ සිතූ දත්ත ඔබට අහිමි වී තිබේද?
මූලාශ්රය: www.habr.com