<?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>Presence on Tarragon</title><link>https://tarrragon.github.io/blog/tags/presence/</link><description>Recent content in Presence on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 23 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/presence/index.xml" rel="self" type="application/rss+xml"/><item><title>2.5 presence store 與即時狀態</title><link>https://tarrragon.github.io/blog/backend/02-cache-redis/presence-store/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/02-cache-redis/presence-store/</guid><description>&lt;p>在線狀態儲存（presence store）的核心責任是維持短生命週期狀態的可查詢性，例如線上狀態、連線節點、最後活動時間。它屬於即時協調層，與正式帳務資料分層治理。&lt;/p>
&lt;h2 id="狀態模型">狀態模型&lt;/h2>
&lt;p>presence 模型通常包含 &lt;code>subject&lt;/code>、&lt;code>node&lt;/code>、&lt;code>last_seen_at&lt;/code>、&lt;code>ttl&lt;/code>。主體可能是使用者、裝置、連線或工作者。模型設計重點是查詢責任：需要查單一主體是否在線、查群組在線清單，還是查節點負載分布。&lt;/p>
&lt;p>presence 資料具備高變動、短保留特性。設計時應避免把正式業務欄位混入 presence store，讓它保持可快速更新與快速過期。&lt;/p>
&lt;h2 id="heartbeat-與-expiration">heartbeat 與 expiration&lt;/h2>
&lt;p>heartbeat 的責任是維持活性訊號，expiration 的責任是清理失效狀態。heartbeat 間隔太長會放大誤判離線，太短會增加寫入壓力。expiration 視窗要和網路抖動容忍度一起設計。&lt;/p>
&lt;p>穩定做法是定義「可接受延遲在線」窗口，而不是追求絕對即時。presence 判讀通常是近即時近似，不是強一致保證。&lt;/p>
&lt;h2 id="cross-node-query">cross-node query&lt;/h2>
&lt;p>跨節點查詢要先明確一致性需求。聊天室在線名單可容忍短暫不一致；調度系統節點可用性則需要更保守窗口與校驗策略。查詢層應同時提供快取讀取與回源校正路徑，避免單一路徑失真。&lt;/p>
&lt;p>在多區部署中，presence 常採區域內優先、跨區聚合延遲同步。這樣能降低廣域寫入成本，同時保留可接受的全域可見性。&lt;/p>
&lt;h2 id="cleanup-策略">cleanup 策略&lt;/h2>
&lt;p>cleanup 的責任是避免殭屍狀態堆積。定期掃描、lazy cleanup、事件驅動清理可混合使用。清理策略要與業務容忍度對齊：社交場景可容忍秒級延遲清除，調度場景則需更快收斂。&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>在線數異常下降但流量未下降&lt;/td>
 &lt;td>heartbeat 發送或寫入路徑中斷&lt;/td>
 &lt;td>檢查 producer 路徑、降級為回源校驗&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>離線判斷延遲明顯增加&lt;/td>
 &lt;td>expiration 視窗過長或清理積壓&lt;/td>
 &lt;td>調整 TTL、提高 cleanup 頻率&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>跨節點查詢結果波動大&lt;/td>
 &lt;td>多節點寫入競態與聚合窗口不一致&lt;/td>
 &lt;td>收斂聚合邏輯、加入版本時間戳&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>節點重啟後出現大量殭屍在線&lt;/td>
 &lt;td>清理與重建流程未對齊&lt;/td>
 &lt;td>啟動全量重整、補啟動時同步清理&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>高峰時段 presence 查詢延遲拉高&lt;/td>
 &lt;td>熱 key 集中與查詢模式不匹配&lt;/td>
 &lt;td>分散 key、按群組分片、加查詢快取&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="常見誤區">常見誤區&lt;/h2>
&lt;p>把在線狀態儲存當正式狀態來源，會讓一致性與修復成本快速上升。presence 模型適合即時協調，最終業務判定仍由正式資料層承擔。&lt;/p>
&lt;p>把 heartbeat 當固定頻率任務，也會造成高峰寫入抖動。頻率應該與線上人數與連線型態一起調整。&lt;/p>
&lt;h2 id="案例回寫">案例回寫&lt;/h2>
&lt;p>presence 模型可用 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta：mcrouter 跨區路由&lt;/a> 回寫。先看跨區路由如何影響在線可見性，再回到本章檢查 heartbeat 視窗、跨節點聚合與清理節奏是否一致。
這個案例主要支撐的是「跨區可見性與狀態新鮮度」判讀，不直接支撐 lock 租約或 queue 語意；若問題是互斥衝突或重播邊界，應轉到 2.4 或 3.x。&lt;/p>
&lt;p>若區域內在線正常、跨區可見性延遲偏大，先調整跨區同步策略與 fallback 壽命，再把影響評估接到 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/customer-impact-assessment/" data-link-title="8.20 Customer Impact Assessment" data-link-desc="把受影響用戶、功能、區域、金額、SLO 與補償判斷串成影響評估模型">8.20 Customer Impact Assessment&lt;/a>。&lt;/p>
&lt;h2 id="跨模組路由">跨模組路由&lt;/h2>
&lt;ol>
&lt;li>與 2.3 的交接：保留與清理策略回到 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">TTL 與 eviction&lt;/a>。&lt;/li>
&lt;li>與 4.17 的交接：presence 資料品質與延遲偏差回到 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">Telemetry Data Quality&lt;/a>。&lt;/li>
&lt;li>與 6.22 的交接：穩態定義與高峰演練回到 &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 前先定義系統應維持的穩定狀態與可接受退化">Steady State Definition&lt;/a>。&lt;/li>
&lt;li>與 8.20 的交接：即時狀態誤判造成客戶影響回到 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/customer-impact-assessment/" data-link-title="8.20 Customer Impact Assessment" data-link-desc="把受影響用戶、功能、區域、金額、SLO 與補償判斷串成影響評估模型">Customer Impact Assessment&lt;/a>。&lt;/li>
&lt;li>與 2.10 的交接：presence 狀態變更如何即時廣播給其他節點回到 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/pub-sub/" data-link-title="2.10 Pub/Sub 與即時 fan-out" data-link-desc="說明 Redis Pub/Sub 的即時廣播責任、at-most-once 邊界，以及何時升級到 Streams 或正式 message queue">Pub/Sub 與即時 fan-out&lt;/a>。&lt;/li>
&lt;/ol>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;p>要看快取層一致性與失效策略，接著讀 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 cache aside 與失效策略&lt;/a>。要看 presence 狀態變更如何即時扇出給其他節點，接著讀 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/pub-sub/" data-link-title="2.10 Pub/Sub 與即時 fan-out" data-link-desc="說明 Redis Pub/Sub 的即時廣播責任、at-most-once 邊界，以及何時升級到 Streams 或正式 message queue">2.10 Pub/Sub 與即時 fan-out&lt;/a>。要看跨規模 presence 路由案例，接著讀 &lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta：mcrouter 跨區路由&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>在線狀態儲存（presence store）的核心責任是維持短生命週期狀態的可查詢性，例如線上狀態、連線節點、最後活動時間。它屬於即時協調層，與正式帳務資料分層治理。</p>
<h2 id="狀態模型">狀態模型</h2>
<p>presence 模型通常包含 <code>subject</code>、<code>node</code>、<code>last_seen_at</code>、<code>ttl</code>。主體可能是使用者、裝置、連線或工作者。模型設計重點是查詢責任：需要查單一主體是否在線、查群組在線清單，還是查節點負載分布。</p>
<p>presence 資料具備高變動、短保留特性。設計時應避免把正式業務欄位混入 presence store，讓它保持可快速更新與快速過期。</p>
<h2 id="heartbeat-與-expiration">heartbeat 與 expiration</h2>
<p>heartbeat 的責任是維持活性訊號，expiration 的責任是清理失效狀態。heartbeat 間隔太長會放大誤判離線，太短會增加寫入壓力。expiration 視窗要和網路抖動容忍度一起設計。</p>
<p>穩定做法是定義「可接受延遲在線」窗口，而不是追求絕對即時。presence 判讀通常是近即時近似，不是強一致保證。</p>
<h2 id="cross-node-query">cross-node query</h2>
<p>跨節點查詢要先明確一致性需求。聊天室在線名單可容忍短暫不一致；調度系統節點可用性則需要更保守窗口與校驗策略。查詢層應同時提供快取讀取與回源校正路徑，避免單一路徑失真。</p>
<p>在多區部署中，presence 常採區域內優先、跨區聚合延遲同步。這樣能降低廣域寫入成本，同時保留可接受的全域可見性。</p>
<h2 id="cleanup-策略">cleanup 策略</h2>
<p>cleanup 的責任是避免殭屍狀態堆積。定期掃描、lazy cleanup、事件驅動清理可混合使用。清理策略要與業務容忍度對齊：社交場景可容忍秒級延遲清除，調度場景則需更快收斂。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>在線數異常下降但流量未下降</td>
          <td>heartbeat 發送或寫入路徑中斷</td>
          <td>檢查 producer 路徑、降級為回源校驗</td>
      </tr>
      <tr>
          <td>離線判斷延遲明顯增加</td>
          <td>expiration 視窗過長或清理積壓</td>
          <td>調整 TTL、提高 cleanup 頻率</td>
      </tr>
      <tr>
          <td>跨節點查詢結果波動大</td>
          <td>多節點寫入競態與聚合窗口不一致</td>
          <td>收斂聚合邏輯、加入版本時間戳</td>
      </tr>
      <tr>
          <td>節點重啟後出現大量殭屍在線</td>
          <td>清理與重建流程未對齊</td>
          <td>啟動全量重整、補啟動時同步清理</td>
      </tr>
      <tr>
          <td>高峰時段 presence 查詢延遲拉高</td>
          <td>熱 key 集中與查詢模式不匹配</td>
          <td>分散 key、按群組分片、加查詢快取</td>
      </tr>
  </tbody>
</table>
<h2 id="常見誤區">常見誤區</h2>
<p>把在線狀態儲存當正式狀態來源，會讓一致性與修復成本快速上升。presence 模型適合即時協調，最終業務判定仍由正式資料層承擔。</p>
<p>把 heartbeat 當固定頻率任務，也會造成高峰寫入抖動。頻率應該與線上人數與連線型態一起調整。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>presence 模型可用 <a href="/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta：mcrouter 跨區路由</a> 回寫。先看跨區路由如何影響在線可見性，再回到本章檢查 heartbeat 視窗、跨節點聚合與清理節奏是否一致。
這個案例主要支撐的是「跨區可見性與狀態新鮮度」判讀，不直接支撐 lock 租約或 queue 語意；若問題是互斥衝突或重播邊界，應轉到 2.4 或 3.x。</p>
<p>若區域內在線正常、跨區可見性延遲偏大，先調整跨區同步策略與 fallback 壽命，再把影響評估接到 <a href="/blog/backend/08-incident-response/customer-impact-assessment/" data-link-title="8.20 Customer Impact Assessment" data-link-desc="把受影響用戶、功能、區域、金額、SLO 與補償判斷串成影響評估模型">8.20 Customer Impact Assessment</a>。</p>
<h2 id="跨模組路由">跨模組路由</h2>
<ol>
<li>與 2.3 的交接：保留與清理策略回到 <a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">TTL 與 eviction</a>。</li>
<li>與 4.17 的交接：presence 資料品質與延遲偏差回到 <a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">Telemetry Data Quality</a>。</li>
<li>與 6.22 的交接：穩態定義與高峰演練回到 <a href="/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">Steady State Definition</a>。</li>
<li>與 8.20 的交接：即時狀態誤判造成客戶影響回到 <a href="/blog/backend/08-incident-response/customer-impact-assessment/" data-link-title="8.20 Customer Impact Assessment" data-link-desc="把受影響用戶、功能、區域、金額、SLO 與補償判斷串成影響評估模型">Customer Impact Assessment</a>。</li>
<li>與 2.10 的交接：presence 狀態變更如何即時廣播給其他節點回到 <a href="/blog/backend/02-cache-redis/pub-sub/" data-link-title="2.10 Pub/Sub 與即時 fan-out" data-link-desc="說明 Redis Pub/Sub 的即時廣播責任、at-most-once 邊界，以及何時升級到 Streams 或正式 message queue">Pub/Sub 與即時 fan-out</a>。</li>
</ol>
<h2 id="下一步路由">下一步路由</h2>
<p>要看快取層一致性與失效策略，接著讀 <a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2 cache aside 與失效策略</a>。要看 presence 狀態變更如何即時扇出給其他節點，接著讀 <a href="/blog/backend/02-cache-redis/pub-sub/" data-link-title="2.10 Pub/Sub 與即時 fan-out" data-link-desc="說明 Redis Pub/Sub 的即時廣播責任、at-most-once 邊界，以及何時升級到 Streams 或正式 message queue">2.10 Pub/Sub 與即時 fan-out</a>。要看跨規模 presence 路由案例，接著讀 <a href="/blog/backend/02-cache-redis/cases/meta-mcrouter-global-cache-routing/" data-link-title="2.C2 Meta：mcrouter 與跨區快取路由" data-link-desc="快取從單點最佳化演進到分散式路由層的案例。">2.C2 Meta：mcrouter 跨區路由</a>。</p>
]]></content:encoded></item></channel></rss>