<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Pinterest on Tarragon</title><link>https://tarrragon.github.io/blog/backend/06-reliability/cases/pinterest/</link><description>Recent content in Pinterest on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 01 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/backend/06-reliability/cases/pinterest/index.xml" rel="self" type="application/rss+xml"/><item><title>Pinterest：Storage Migration 與 Data Infrastructure Reliability</title><link>https://tarrragon.github.io/blog/backend/06-reliability/cases/pinterest/storage-migration-and-data-infrastructure-reliability/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/cases/pinterest/storage-migration-and-data-infrastructure-reliability/</guid><description>&lt;p>Storage migration 的可靠性責任是讓資料基礎設施的變更可漸進、可驗證、可回退。PB 級資料的儲存引擎遷移（如 HBase → TiDB）牽涉 schema mapping、query pattern 差異與 consistency model 變更，任何一處不相容都會在 production 流量下被放大。&lt;/p>
&lt;h2 id="問題場景">問題場景&lt;/h2>
&lt;p>Pinterest 的資料基礎設施服務數十億 pin、推薦系統與搜尋索引。當儲存引擎需要退役或升級時，直接 cutover 的風險在於所有不相容同時暴露 — query 語意差異、pagination 行為、null handling、ordering 規則都可能在切換瞬間衝擊線上流量。&lt;/p>
&lt;p>漸進遷移的設計核心是把一次性 cutover 拆成可觀測的多階段流程，每個階段都有回退路徑。&lt;/p>
&lt;h2 id="決策機制">決策機制&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>機制&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>交付結果&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Dual-write&lt;/td>
 &lt;td>新舊系統的寫入是否同步且完整&lt;/td>
 &lt;td>資料不遺失保證&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Shadow read&lt;/td>
 &lt;td>新舊系統的讀取結果是否一致&lt;/td>
 &lt;td>行為差異清單&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Reconciliation&lt;/td>
 &lt;td>兩套系統的資料是否持續一致&lt;/td>
 &lt;td>一致性報告&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Staged cutover&lt;/td>
 &lt;td>何時可以把流量從舊系統切到新系統&lt;/td>
 &lt;td>漸進切換節奏&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Dual-write 確保遷移期間每筆寫入同時進入新舊系統。寫入失敗的處理策略決定資料完整性 — 若新系統寫入失敗是否 block 舊系統的寫入，取決於遷移階段（早期容許新系統 fail-open、接近 cutover 時需要 fail-close）。&lt;/p>
&lt;p>Shadow read 在真實流量下比對新舊系統的查詢結果。比對維度包含回傳資料的完整性、排序、分頁邊界與 null 值處理。mismatch rate 是 cutover 可行性的核心判準 — rate 趨近零才能進入下一批切換。&lt;/p>
&lt;p>Staged cutover 按 traffic percentage、data partition 或 use case 漸進切換。每一批觀察 mismatch rate、latency overhead 與 error rate，任一指標超門檻即回退到舊系統。&lt;/p>
&lt;h2 id="可觀測訊號">可觀測訊號&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>判讀重點&lt;/th>
 &lt;th>對應章節&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>shadow read mismatch rate&lt;/td>
 &lt;td>新舊系統行為差異是否收斂&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>dual-write latency overhead&lt;/td>
 &lt;td>同步寫入是否拖累主路徑&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>reconciliation gap&lt;/td>
 &lt;td>兩套系統資料是否持續一致&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>cutover rollback count&lt;/td>
 &lt;td>切換過程是否穩定&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="常見陷阱">常見陷阱&lt;/h2>
&lt;p>Shadow read 比對容易只看最終結果是否相同，忽略中間狀態的差異。pagination 的邊界行為、null 欄位的回傳語意、排序在 tie-breaking 時的規則 — 這些差異在主流程不明顯，但在邊界情境會爆發。reconciliation 需要覆蓋 edge case，包含空集合回傳、大量資料分頁與 concurrent write 衝突。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11 migration safety&lt;/a>：storage migration 的 schema 相容與 rollout 策略&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7 DR rollback rehearsal&lt;/a>：cutover 失敗時的 rollback 路徑&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 performance regression gate&lt;/a>：dual-write latency 作為 regression 偵測&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23 verification evidence handoff&lt;/a>：reconciliation 結果作為 cutover 決策證據&lt;/li>
&lt;/ul>
&lt;h2 id="引用源">引用源&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://medium.com/pinterest-engineering/online-data-migration-from-hbase-to-tidb-with-zero-downtime-43f0fb474b84">Online Data Migration from HBase to TiDB with Zero Downtime&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/pinterest-engineering/hbase-deprecation-at-pinterest-8a99e6c8e6b7">HBase Deprecation at Pinterest&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Storage migration 的可靠性責任是讓資料基礎設施的變更可漸進、可驗證、可回退。PB 級資料的儲存引擎遷移（如 HBase → TiDB）牽涉 schema mapping、query pattern 差異與 consistency model 變更，任何一處不相容都會在 production 流量下被放大。</p>
<h2 id="問題場景">問題場景</h2>
<p>Pinterest 的資料基礎設施服務數十億 pin、推薦系統與搜尋索引。當儲存引擎需要退役或升級時，直接 cutover 的風險在於所有不相容同時暴露 — query 語意差異、pagination 行為、null handling、ordering 規則都可能在切換瞬間衝擊線上流量。</p>
<p>漸進遷移的設計核心是把一次性 cutover 拆成可觀測的多階段流程，每個階段都有回退路徑。</p>
<h2 id="決策機制">決策機制</h2>
<table>
  <thead>
      <tr>
          <th>機制</th>
          <th>核心問題</th>
          <th>交付結果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Dual-write</td>
          <td>新舊系統的寫入是否同步且完整</td>
          <td>資料不遺失保證</td>
      </tr>
      <tr>
          <td>Shadow read</td>
          <td>新舊系統的讀取結果是否一致</td>
          <td>行為差異清單</td>
      </tr>
      <tr>
          <td>Reconciliation</td>
          <td>兩套系統的資料是否持續一致</td>
          <td>一致性報告</td>
      </tr>
      <tr>
          <td>Staged cutover</td>
          <td>何時可以把流量從舊系統切到新系統</td>
          <td>漸進切換節奏</td>
      </tr>
  </tbody>
</table>
<p>Dual-write 確保遷移期間每筆寫入同時進入新舊系統。寫入失敗的處理策略決定資料完整性 — 若新系統寫入失敗是否 block 舊系統的寫入，取決於遷移階段（早期容許新系統 fail-open、接近 cutover 時需要 fail-close）。</p>
<p>Shadow read 在真實流量下比對新舊系統的查詢結果。比對維度包含回傳資料的完整性、排序、分頁邊界與 null 值處理。mismatch rate 是 cutover 可行性的核心判準 — rate 趨近零才能進入下一批切換。</p>
<p>Staged cutover 按 traffic percentage、data partition 或 use case 漸進切換。每一批觀察 mismatch rate、latency overhead 與 error rate，任一指標超門檻即回退到舊系統。</p>
<h2 id="可觀測訊號">可觀測訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>shadow read mismatch rate</td>
          <td>新舊系統行為差異是否收斂</td>
          <td><a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11</a></td>
      </tr>
      <tr>
          <td>dual-write latency overhead</td>
          <td>同步寫入是否拖累主路徑</td>
          <td><a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13</a></td>
      </tr>
      <tr>
          <td>reconciliation gap</td>
          <td>兩套系統資料是否持續一致</td>
          <td><a href="/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23</a></td>
      </tr>
      <tr>
          <td>cutover rollback count</td>
          <td>切換過程是否穩定</td>
          <td><a href="/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7</a></td>
      </tr>
  </tbody>
</table>
<h2 id="常見陷阱">常見陷阱</h2>
<p>Shadow read 比對容易只看最終結果是否相同，忽略中間狀態的差異。pagination 的邊界行為、null 欄位的回傳語意、排序在 tie-breaking 時的規則 — 這些差異在主流程不明顯，但在邊界情境會爆發。reconciliation 需要覆蓋 edge case，包含空集合回傳、大量資料分頁與 concurrent write 衝突。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li><a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11 migration safety</a>：storage migration 的 schema 相容與 rollout 策略</li>
<li><a href="/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7 DR rollback rehearsal</a>：cutover 失敗時的 rollback 路徑</li>
<li><a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 performance regression gate</a>：dual-write latency 作為 regression 偵測</li>
<li><a href="/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23 verification evidence handoff</a>：reconciliation 結果作為 cutover 決策證據</li>
</ul>
<h2 id="引用源">引用源</h2>
<ul>
<li><a href="https://medium.com/pinterest-engineering/online-data-migration-from-hbase-to-tidb-with-zero-downtime-43f0fb474b84">Online Data Migration from HBase to TiDB with Zero Downtime</a></li>
<li><a href="https://medium.com/pinterest-engineering/hbase-deprecation-at-pinterest-8a99e6c8e6b7">HBase Deprecation at Pinterest</a></li>
</ul>
]]></content:encoded></item><item><title>Pinterest：快取可靠性與容量驚奇治理</title><link>https://tarrragon.github.io/blog/backend/06-reliability/cases/pinterest/cache-reliability-and-capacity-surprises/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/06-reliability/cases/pinterest/cache-reliability-and-capacity-surprises/</guid><description>&lt;p>Pinterest 案例的核心責任是處理快取層造成的容量驚奇。快取命中率下滑會在短時間放大到資料層與下游依賴，因此需要預先設計退化與重建節奏。&lt;/p>
&lt;h2 id="問題場景">問題場景&lt;/h2>
&lt;p>流量高峰或快取失溫時，回源壓力會瞬間上升。若沒有緩衝機制與重建策略，系統容易進入連鎖退化。&lt;/p>
&lt;h2 id="決策機制">決策機制&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>機制&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>交付結果&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Cache headroom&lt;/td>
 &lt;td>命中率下滑能承受多久&lt;/td>
 &lt;td>容量緩衝&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Graceful degradation&lt;/td>
 &lt;td>快取失效時如何降級&lt;/td>
 &lt;td>服務連續性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Rewarm strategy&lt;/td>
 &lt;td>熱資料如何有序回填&lt;/td>
 &lt;td>恢復節奏&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀測訊號">可觀測訊號&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>判讀重點&lt;/th>
 &lt;th>對應章節&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>cache hit ratio drop&lt;/td>
 &lt;td>是否進入危險區&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>fallback latency&lt;/td>
 &lt;td>降級路徑是否可接受&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">6.22&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>rewarm backlog&lt;/td>
 &lt;td>回填是否可收斂&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;p>先在 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/load-testing/" data-link-title="6.2 load test" data-link-desc="把 production 流量結構轉成可重播壓力情境，定位 saturation 轉折與容量邊界">6.2&lt;/a> 模擬命中率崩落，再把恢復證據寫入 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Pinterest 案例的核心責任是處理快取層造成的容量驚奇。快取命中率下滑會在短時間放大到資料層與下游依賴，因此需要預先設計退化與重建節奏。</p>
<h2 id="問題場景">問題場景</h2>
<p>流量高峰或快取失溫時，回源壓力會瞬間上升。若沒有緩衝機制與重建策略，系統容易進入連鎖退化。</p>
<h2 id="決策機制">決策機制</h2>
<table>
  <thead>
      <tr>
          <th>機制</th>
          <th>核心問題</th>
          <th>交付結果</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cache headroom</td>
          <td>命中率下滑能承受多久</td>
          <td>容量緩衝</td>
      </tr>
      <tr>
          <td>Graceful degradation</td>
          <td>快取失效時如何降級</td>
          <td>服務連續性</td>
      </tr>
      <tr>
          <td>Rewarm strategy</td>
          <td>熱資料如何有序回填</td>
          <td>恢復節奏</td>
      </tr>
  </tbody>
</table>
<h2 id="可觀測訊號">可觀測訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>cache hit ratio drop</td>
          <td>是否進入危險區</td>
          <td><a href="/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9</a></td>
      </tr>
      <tr>
          <td>fallback latency</td>
          <td>降級路徑是否可接受</td>
          <td><a href="/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">6.22</a></td>
      </tr>
      <tr>
          <td>rewarm backlog</td>
          <td>回填是否可收斂</td>
          <td><a href="/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3</a></td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<p>先在 <a href="/blog/backend/06-reliability/load-testing/" data-link-title="6.2 load test" data-link-desc="把 production 流量結構轉成可重播壓力情境，定位 saturation 轉折與容量邊界">6.2</a> 模擬命中率崩落，再把恢復證據寫入 <a href="/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23</a>。</p>
]]></content:encoded></item></channel></rss>