revise May 2021 distributed lock articles
Build and deploy / deploy (push) Successful in 15s

This commit is contained in:
2026-07-31 12:37:36 +03:00
parent c561263bfc
commit 32e0550f4f
7 changed files with 1101 additions and 1 deletions
@@ -0,0 +1,91 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1620" role="img" aria-labelledby="title desc">
<title id="title">Диагностика позднего владельца lease</title>
<desc id="desc">Вертикальное дерево разбора поздней записи. Сначала собираются resource key и fencing token, затем различаются устаревшее поколение, повтор операции, ресурс без fencing и неверный release.</desc>
<defs>
<marker id="arrow" viewBox="0 0 12 12" refX="10" refY="6" markerWidth="10" markerHeight="10" orient="auto-start-reverse">
<path d="M1 1 L11 6 L1 11z" fill="#9fb7d7"/>
</marker>
<style>
.bg { fill: #0b1324; }
.card { fill: #14213a; stroke: #42658f; stroke-width: 3; }
.decision { fill: #173e45; stroke: #48c5be; stroke-width: 3; }
.ok { fill: #1a4136; stroke: #67d5a6; stroke-width: 3; }
.warn { fill: #422a30; stroke: #ff9a80; stroke-width: 3; }
.line { stroke: #9fb7d7; stroke-width: 5; fill: none; marker-end: url(#arrow); }
.branch { stroke: #ffb270; stroke-width: 5; fill: none; marker-end: url(#arrow); }
.title { fill: #ffffff; font: 700 34px Arial, sans-serif; }
.label { fill: #eaf2ff; font: 600 27px Arial, sans-serif; }
.body { fill: #d2def2; font: 24px Arial, sans-serif; }
.small { fill: #b6c7e3; font: 22px Arial, sans-serif; }
.tag { fill: #87e5db; font: 700 21px Arial, sans-serif; letter-spacing: 1px; }
.yes { fill: #93e5ba; font: 700 22px Arial, sans-serif; }
.no { fill: #ffcb99; font: 700 22px Arial, sans-serif; }
</style>
</defs>
<rect class="bg" width="720" height="1620" rx="32"/>
<text x="360" y="62" text-anchor="middle" class="title">Разбор поздней записи</text>
<text x="360" y="96" text-anchor="middle" class="small">сначала факт ресурса, затем причина</text>
<rect x="80" y="140" width="560" height="160" rx="22" class="card"/>
<text x="115" y="183" class="tag">1 · СОБРАТЬ EVIDENCE</text>
<text x="115" y="225" class="label">resource key · leaseId · token</text>
<text x="115" y="258" class="body">highest token до и после write</text>
<path d="M360 300 L360 352" class="line"/>
<rect x="80" y="352" width="560" height="156" rx="22" class="decision"/>
<text x="115" y="394" class="tag">2 · СРАВНИТЬ</text>
<text x="115" y="436" class="label">token меньше highest token?</text>
<text x="115" y="469" class="body">это один и тот же resource key?</text>
<path d="M222 508 L222 565" class="line"/>
<path d="M498 508 L498 565" class="branch"/>
<text x="166" y="550" class="yes">ДА</text>
<text x="470" y="550" class="no">НЕТ</text>
<rect x="52" y="585" width="340" height="188" rx="22" class="ok"/>
<text x="82" y="626" class="tag">STALE GENERATION</text>
<text x="82" y="668" class="label">resource уже принял</text>
<text x="82" y="701" class="body">более новый token</text>
<text x="82" y="734" class="small">reject stale write; не retry</text>
<rect x="428" y="585" width="240" height="188" rx="22" class="decision"/>
<text x="458" y="626" class="tag">ДАЛЬШЕ</text>
<text x="458" y="668" class="label">проверить</text>
<text x="458" y="701" class="body">operationId</text>
<text x="458" y="734" class="small">и оба write</text>
<path d="M548 773 L548 830" class="branch"/>
<rect x="428" y="850" width="240" height="176" rx="22" class="card"/>
<text x="458" y="891" class="tag">DUPLICATE?</text>
<text x="458" y="933" class="label">тот же effect</text>
<text x="458" y="966" class="body">с тем же id?</text>
<text x="458" y="999" class="small">да → ledger policy</text>
<path d="M548 1026 L548 1083" class="branch"/>
<rect x="428" y="1103" width="240" height="176" rx="22" class="warn"/>
<text x="458" y="1144" class="tag">BOTH ACCEPTED</text>
<text x="458" y="1186" class="label">ресурс пишет</text>
<text x="458" y="1219" class="body">без compare</text>
<text x="548" y="1252" text-anchor="middle" class="small">atomic compare + fence</text>
<path d="M222 773 L222 830" class="line"/>
<rect x="52" y="850" width="340" height="176" rx="22" class="card"/>
<text x="82" y="891" class="tag">RELEASE CHECK</text>
<text x="82" y="933" class="label">старый handle снимает</text>
<text x="82" y="966" class="body">lease нового worker?</text>
<text x="82" y="999" class="small">сверить exact lease handle</text>
<path d="M222 1026 L222 1083" class="line"/>
<rect x="52" y="1103" width="340" height="176" rx="22" class="decision"/>
<text x="82" y="1144" class="tag">SCOPE CHECK</text>
<text x="82" y="1186" class="label">один lockName, но</text>
<text x="82" y="1219" class="body">разные resource key?</text>
<text x="82" y="1252" class="small">пересмотреть границу token</text>
<path d="M360 1279 L360 1336" class="line"/>
<rect x="80" y="1356" width="560" height="172" rx="22" class="ok"/>
<text x="115" y="1397" class="tag">ИТОГ</text>
<text x="115" y="1439" class="label">Назвать конкретный stale result</text>
<text x="115" y="1472" class="label">и следующий test</text>
<text x="115" y="1505" class="small">Lock log без resource evidence не является гарантией.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1,65 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1500" role="img" aria-labelledby="title desc">
<title id="title">Граница fencing token между lock authority и ресурсом</title>
<desc id="desc">Вертикальная схема показывает, что lock authority выдаёт lease и поколения владения, а защищаемый ресурс хранит наибольший принятый token. Token два принимается, а поздний token один отклоняется внутри ресурса.</desc>
<defs>
<marker id="arrow" viewBox="0 0 12 12" refX="10" refY="6" markerWidth="10" markerHeight="10" orient="auto-start-reverse">
<path d="M1 1 L11 6 L1 11z" fill="#9fb7d7"/>
</marker>
<style>
.bg { fill: #0b1324; }
.authority { fill: #173e45; stroke: #48c5be; stroke-width: 3; }
.worker { fill: #14213a; stroke: #42658f; stroke-width: 3; }
.resource { fill: #1a4136; stroke: #67d5a6; stroke-width: 3; }
.warn { fill: #422a30; stroke: #ff9a80; stroke-width: 3; }
.line { stroke: #9fb7d7; stroke-width: 5; fill: none; marker-end: url(#arrow); }
.warnline { stroke: #ff9a80; stroke-width: 5; fill: none; marker-end: url(#arrow); }
.title { fill: #ffffff; font: 700 34px Arial, sans-serif; }
.label { fill: #eaf2ff; font: 600 27px Arial, sans-serif; }
.body { fill: #d2def2; font: 24px Arial, sans-serif; }
.small { fill: #b6c7e3; font: 22px Arial, sans-serif; }
.tag { fill: #87e5db; font: 700 21px Arial, sans-serif; letter-spacing: 1px; }
.badtag { fill: #ffbfaa; font: 700 21px Arial, sans-serif; letter-spacing: 1px; }
</style>
</defs>
<rect class="bg" width="720" height="1500" rx="32"/>
<text x="360" y="62" text-anchor="middle" class="title">Fence живёт в ресурсе</text>
<text x="360" y="96" text-anchor="middle" class="small">lease и write отвечают на разные вопросы</text>
<rect x="72" y="142" width="576" height="173" rx="22" class="authority"/>
<text x="108" y="185" class="tag">LOCK AUTHORITY</text>
<text x="108" y="227" class="label">выдаёт lease-1 / token 1</text>
<text x="108" y="260" class="body">знает lifecycle текущего lock</text>
<text x="108" y="292" class="small">не меняет защищаемый ресурс</text>
<path d="M360 315 L360 367" class="line"/>
<rect x="72" y="367" width="576" height="161" rx="22" class="worker"/>
<text x="108" y="409" class="tag">WORKER-A</text>
<text x="108" y="451" class="label">пауза дольше lease</text>
<text x="108" y="484" class="body">старый payload и token 1 остаются</text>
<path d="M360 528 L360 580" class="line"/>
<rect x="72" y="580" width="576" height="174" rx="22" class="authority"/>
<text x="108" y="622" class="tag">LOCK AUTHORITY AFTER EXPIRY</text>
<text x="108" y="664" class="label">выдаёт lease-2 / token 2</text>
<text x="108" y="697" class="body">worker-B становится новым владельцем</text>
<text x="108" y="729" class="small">expiry не отзывает request от worker-A</text>
<path d="M360 754 L360 806" class="line"/>
<rect x="72" y="806" width="576" height="178" rx="22" class="resource"/>
<text x="108" y="848" class="tag">PROTECTED RESOURCE</text>
<text x="108" y="890" class="label">принимает write с token 2</text>
<text x="108" y="923" class="body">сохраняет value v2 и highest token 2</text>
<text x="108" y="956" class="small">сравнение и write — одна граница</text>
<path d="M360 984 L360 1036" class="warnline"/>
<rect x="72" y="1036" width="576" height="179" rx="22" class="warn"/>
<text x="108" y="1078" class="badtag">LATE REQUEST FROM WORKER-A</text>
<text x="108" y="1120" class="label">token 1 ≤ highest token 2</text>
<text x="108" y="1153" class="body">resource returns rejected-stale-fence</text>
<text x="108" y="1186" class="small">authority не обязан участвовать в этом write</text>
<rect x="72" y="1270" width="576" height="150" rx="22" fill="#14213a" stroke="#42658f" stroke-width="3"/>
<text x="360" y="1312" text-anchor="middle" class="label">Без проверки в ресурсе</text>
<text x="360" y="1348" text-anchor="middle" class="label">поздний v1 может перезаписать v2</text>
<text x="360" y="1384" text-anchor="middle" class="small">Сам lock не доказывает безопасность внешнего эффекта.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,82 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1420" role="img" aria-labelledby="title desc">
<title id="title">Истечение lease и поздняя запись старого worker</title>
<desc id="desc">Вертикальная временная шкала учебного сценария: worker-A получает lease один и token один, останавливается после истечения lease, worker-B получает lease два и token два, ресурс принимает token два и отвергает поздний token один.</desc>
<defs>
<marker id="arrow" viewBox="0 0 12 12" refX="10" refY="6" markerWidth="10" markerHeight="10" orient="auto-start-reverse">
<path d="M1 1 L11 6 L1 11z" fill="#9fb7d7"/>
</marker>
<style>
.bg { fill: #0b1324; }
.card { fill: #14213a; stroke: #42658f; stroke-width: 3; }
.accent { fill: #173e45; stroke: #48c5be; stroke-width: 3; }
.ok { fill: #1a4136; stroke: #67d5a6; stroke-width: 3; }
.warn { fill: #422a30; stroke: #ff9a80; stroke-width: 3; }
.muted { fill: #2a3040; stroke: #71819d; stroke-width: 3; }
.line { stroke: #9fb7d7; stroke-width: 5; fill: none; marker-end: url(#arrow); }
.dash { stroke: #71819d; stroke-width: 4; fill: none; stroke-dasharray: 10 10; }
.title { fill: #ffffff; font: 700 34px Arial, sans-serif; }
.label { fill: #eaf2ff; font: 600 27px Arial, sans-serif; }
.body { fill: #d2def2; font: 24px Arial, sans-serif; }
.small { fill: #b6c7e3; font: 22px Arial, sans-serif; }
.tag { fill: #87e5db; font: 700 21px Arial, sans-serif; letter-spacing: 1px; }
.time { fill: #ffcf8b; font: 700 24px Arial, sans-serif; }
</style>
</defs>
<rect class="bg" width="720" height="1420" rx="32"/>
<text x="360" y="62" text-anchor="middle" class="title">Lease не отменяет старый request</text>
<text x="360" y="96" text-anchor="middle" class="small">учебный interleaving без реального provider</text>
<path d="M118 160 L118 1300" class="dash"/>
<text x="118" y="151" text-anchor="middle" class="small">время</text>
<text x="42" y="210" class="time">t=0</text>
<circle cx="118" cy="201" r="13" fill="#48c5be"/>
<rect x="166" y="145" width="500" height="142" rx="22" class="accent"/>
<text x="198" y="186" class="tag">WORKER-A · ACQUIRE</text>
<text x="198" y="228" class="label">lease-1, fence token 1</text>
<text x="198" y="261" class="body">критическая работа начинается</text>
<path d="M416 287 L416 339" class="line"/>
<text x="25" y="386" class="time">t=5000</text>
<circle cx="118" cy="378" r="13" fill="#ffb270"/>
<rect x="166" y="339" width="500" height="138" rx="22" class="muted"/>
<text x="198" y="380" class="tag">LEASE LIMIT</text>
<text x="198" y="422" class="label">worker-A всё ещё paused</text>
<text x="198" y="455" class="body">его память не очищается</text>
<path d="M416 477 L416 529" class="line"/>
<text x="25" y="578" class="time">t=6000</text>
<circle cx="118" cy="569" r="13" fill="#ff9a80"/>
<rect x="166" y="529" width="500" height="151" rx="22" class="warn"/>
<text x="198" y="571" class="tag">AUTHORITY</text>
<text x="198" y="613" class="label">lease-1 истёк и освобождён</text>
<text x="198" y="646" class="body">это не остановка worker-A</text>
<path d="M416 680 L416 732" class="line"/>
<text x="25" y="780" class="time">t=6000</text>
<circle cx="118" cy="771" r="13" fill="#48c5be"/>
<rect x="166" y="732" width="500" height="160" rx="22" class="accent"/>
<text x="198" y="774" class="tag">WORKER-B · ACQUIRE</text>
<text x="198" y="816" class="label">lease-2, fence token 2</text>
<text x="198" y="849" class="body">новое поколение владельца</text>
<path d="M416 892 L416 944" class="line"/>
<text x="25" y="993" class="time">t=6100</text>
<circle cx="118" cy="984" r="13" fill="#67d5a6"/>
<rect x="166" y="944" width="500" height="153" rx="22" class="ok"/>
<text x="198" y="986" class="tag">PROTECTED RESOURCE</text>
<text x="198" y="1028" class="label">write token 2 → accepted</text>
<text x="198" y="1061" class="body">highest accepted token = 2</text>
<path d="M416 1097 L416 1149" class="line"/>
<text x="25" y="1198" class="time">t=6200</text>
<circle cx="118" cy="1189" r="13" fill="#ff9a80"/>
<rect x="166" y="1149" width="500" height="190" rx="22" class="warn"/>
<text x="198" y="1191" class="tag">LATE REQUEST FROM A</text>
<text x="198" y="1233" class="label">write token 1 → rejected</text>
<text x="198" y="1266" class="body">ресурс не даёт v1 перезаписать v2</text>
<text x="198" y="1298" class="small">без resource-side fence</text>
<text x="198" y="1326" class="small">обе записи допустимы</text>
<text x="360" y="1372" text-anchor="middle" class="small">Lock координирует владение; ресурс проверяет поколение.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB