題幹與適用情境
這道題只討論 Feature Flag 的評估熱路徑。控制台、審批與完整平台建設屬於另一道設計題;這裡要解決設定非同步傳播、呼叫方使用不同語言 SDK 時,同一使用者仍得到可解釋、可重現的變體。假設評估在服務端程序內完成,規則支援屬性比對與百分比分流。
面試官考察重點
- 能否分開處理「設定最終一致」與「單一使用者分桶穩定」。
- 是否定義唯一
targetingKey、正規化規則及跨 SDK 一致的雜湊演算法。 - 是否以不可變快照和單調版本切換設定,避免一次請求讀到半份新設定。
- 是否處理上下文缺失、型別錯誤、未知旗標與設定過期時的預設值。
- 能否用黃金測試向量、影子評估和分布指標證明一致性。
回答前需要釐清的問題
先確認穩定性的邊界:同一使用者是否要跨裝置、跨區域與跨語言 SDK 命中同一變體;匿名使用者採用哪個穩定識別;擴大灰度比例時,原本 10% 使用者是否必須留在新版本。還要確認規則屬性是否含敏感資料、設定可容忍多久不一致,以及緊急關閉能否覆蓋一般百分比分流。
30 秒回答架構
我會把規則編譯成帶版本的不可變快照,在 SDK 本機評估。百分比分流先把 targetingKey、flagKey 和種子編碼成帶長度邊界的正規元組,再做確定性雜湊並映射到固定桶區間。一般變更先分發尚未生效的快照,等所有服務區域確認就緒後,由控制面推進唯一的分配世代;工作階段或持久身分始終攜帶該世代,執行個體在有限重疊期內同時保留新舊快照,因此本機時鐘偏差不會讓使用者切換規則版本。上下文缺失、規則型別錯誤或設定過期時回傳呼叫方預設值及原因碼,上線前用跨語言黃金向量和影子評估驗證一致性。
分步深入解析
先固定輸入契約。每次服務端評估都要提供非空 targetingKey;匿名流量可用持久化匿名 ID,不能每次請求重新產生。字串編碼、大小寫、空白、數字與時間格式必須寫入協議。雜湊輸入使用帶版本號和長度前綴的 UTF-8 元組,不能直接串接字串或只依賴分隔符,否則欄位邊界和值中的特殊字元會在不同 SDK 中產生歧義。
分桶函式可定義為 bucket = hash(encodeTuple(v, seed, flagKey, targetingKey)) mod 100000。每個變體佔用不重疊的連續區間。10% 擴至 20% 時只擴大目標區間,原先命中的使用者會保留。flagKey 避免不同旗標產生完全相關樣本;需要重新洗牌時明確更換 seed,並視為有稽核記錄的破壞性操作。
規則比對與分桶必須使用同一個不可變快照。分發器先把帶校驗和與單調版本的未生效快照送達所有服務區域。區域全部校驗並確認就緒後,控制面推進唯一的分配世代;工作階段權杖或持久身分記錄攜帶該世代,每個區域依請求引用的版本評估,並在分配有效期結束前保留舊快照。缺少引用版本的執行個體停止承接該請求。這套協議依賴版本傳遞,不依賴各節點時鐘同步。緊急關閉可以明確覆蓋黏性,以安全優先並保留版本記錄。
OpenFeature 評估介面允許呼叫方提供預設值,異常時應回傳該值及錯誤原因。實作要區分旗標不存在、型別不符、缺少 targetingKey 與 provider 尚未就緒。指標只記錄低基數欄位,電子郵件、裝置識別等敏感上下文不可進入一般日誌。
驗證分三層:各 SDK 執行相同黃金輸入與期望變體,覆蓋空值、分隔符、Unicode 和欄位邊界碰撞;發布前用生產形狀快照影子評估,比較新舊引擎並演練區域就緒失敗;上線後觀察變體比例、預設值命中率、快照年齡與區域版本分布。比例偏差只作告警線索,單一決定仍應由快照版本、規則 ID 與桶位重算。
高品質示範回答
我會讓每個 SDK 只評估通過校驗的完整快照。請求提供穩定 targetingKey,SDK 將版本化、帶長度邊界的 seed、flagKey 與 targetingKey 元組做統一雜湊,再映射到十萬個固定桶;灰度擴容只調整桶區間,因此既有使用者不會掉出目標變體。
一般變更先送達所有區域,再由控制面推進分配世代。工作階段或持久身分攜帶該世代,每個區域在分配有效期內保留並評估請求引用的快照,因此跨區域請求無須依賴時鐘同步也只讀取一個規則版本。缺少該快照的執行個體停止承接請求。SDK 拒絕版本倒退,設定過期或上下文無效時回傳呼叫方預設值;緊急關閉則明確覆蓋一般黏性並優先收斂。
常見錯誤
- 每次評估呼叫遠端服務,把業務可用性綁在設定網路上。
- 使用語言執行時內建雜湊,導致不同程序或 SDK 結果不一致。
- 只對使用者 ID 雜湊,使所有旗標樣本高度相關。
- 設定逐欄位更新,讓請求同時讀到新規則與舊權重。
- 缺少
targetingKey時隨機分桶,造成使用者持續跳變。 - 為除錯記錄完整評估上下文,擴大隱私暴露面。
追問與回答
設定版本不同,怎樣確保跨區域完全一致?
非同步分發本身無法承諾零窗口的全域強一致。一般變更先完成所有服務區域的就緒確認,再由控制面推進一個分配世代,並由工作階段或持久身分在每個請求中攜帶該世代。各區域保留被引用的快照直到分配過期,缺少該版本的執行個體退出服務。緊急關閉可以覆蓋黏性,優先快速收斂並監控尚未更新的執行個體。
匿名使用者沒有帳號 ID 怎麼辦?
使用客戶端持久化的隨機匿名 ID,並說明清除儲存或更換裝置後會重新分桶。IP 會共享和改變,也帶來隱私問題,不適合作為穩定身份。
如何安全更換雜湊演算法?
將演算法版本和種子寫入快照,先影子計算新舊桶位並量測遷移比例。需要保留黏性時建立過渡映射;允許重新抽樣時,也要把切換視為明確發布並保留回滾版本。
如何發現某個 SDK 實作偏差?
所有 SDK 執行同一組黃金測試向量,並定期上報低基數的演算法版本、快照版本與聚合變體計數。發現偏差時凍結該 SDK 的設定升級、保留最近有效快照,再修正正規化或雜湊實作。