架構(gòu)師必備:灰度方案匯總

大家好,我是Java烘焙師。本文結(jié)合筆者的經(jīng)驗和思考,對灰度方案做個總結(jié),重點介紹AB實驗。

灰度在開發(fā)流程中非常普遍。先做小流量驗證,確認無誤后再推全,灰度過程中一旦發(fā)現(xiàn)系統(tǒng)異常、或業(yè)務(wù)指標異常,應(yīng)立刻回滾。

灰度場景

  • 代碼灰度:是最典型的灰度,灰度內(nèi)做新邏輯,灰度外做舊邏輯
    • 既可以提供v2版本新接口給調(diào)用方服務(wù),由調(diào)用方來做灰度切換
    • 也可以內(nèi)部切灰度,做到調(diào)用方無感
  • 發(fā)版灰度:上線過程中,新版本服務(wù)實例不斷增加,需考慮兼容新舊協(xié)議
  • 配置灰度:修改配置時,按服務(wù)實例灰度推送配置變更

灰度模式

  • 數(shù)字id尾號灰度:取id最后2位(百分比)、最后3位(千分比)、最后4位(萬分比)等
    • 實現(xiàn)方式:id取模,例如 id % 100 < 灰度百分比,則命中灰度
    • 特點:簡單,適用于絕大部分技術(shù)優(yōu)化場景
  • 隨機灰度:取一部分隨機流量做灰度
    • 實現(xiàn)方式:ThreadLocalRandom.current().nextInt(100) < 灰度百分比
    • 之所以使用ThreadLocalRandom、而不是Random,是為了避免多線程競爭用于生成隨機數(shù)的seed
  • A/B實驗
    • 實現(xiàn)方式:分層實驗、實驗數(shù)據(jù)收集、離線統(tǒng)計
    • 特點:適用于小流量驗證新業(yè)務(wù)功能的效果,整體方案相對復(fù)雜,需要技術(shù)基建

id選取

  • 業(yè)務(wù)id:如用戶id、商品id等
  • 設(shè)備id:未注冊/未登錄用戶,此時沒有用戶id,只能取設(shè)備的唯一標識

下面重點介紹一下A/B實驗。

A/B實驗

目的

  • 小流量驗證新業(yè)務(wù)功能,正向顯著則推至全量,否則繼續(xù)迭代優(yōu)化、或下線,避免功能過于臃腫
  • 用數(shù)據(jù)作為依據(jù),避免想當(dāng)然、拍腦袋決策

分層實驗

主要目的是為了同時做多個實驗,而不是給每個實驗均分一部分流量。因為當(dāng)同時進行的實驗變多時,組合數(shù)量成倍增加,每個實驗分到的流量就很少了。
有這幾層結(jié)構(gòu):實驗層、實驗、分組

  • 實驗層之間正交,可同時進行多個實驗層的實驗
  • 同一實驗層的實驗之間互斥,比如命中了實驗1-1,就不會命中實驗1-2。實驗持有0到多個分桶,根據(jù)業(yè)務(wù)id可計算出桶號,進而知道命中哪個實驗
  • 同一實驗內(nèi)有多個分組,包括1個對照組,和1到多個實驗組,只會命中其中一個分組。分組持有0到多個分桶,根據(jù)業(yè)務(wù)id可計算出桶號,進而知道命中哪個分組

實驗層、實驗舉例:

  • 展示實驗層:根據(jù)頁面進行劃分,如首頁、搜索頁、推薦頁、詳情頁等。每個頁面作為一個實驗層,每個實驗層里可同時做多個展示實驗
  • 算法實驗層:根據(jù)場景進行劃分,如相似推薦、搭配購?fù)扑]、個性化推薦、搜索排序、廣告排序等。每個場景作為一個實驗層,每個實驗層里可同時做多個算法實驗
image.png

哈希算法打散

要同時支持多個分層實驗,核心在于通過哈希算法將每一層的流量打散,用于實現(xiàn)“均勻分流”和“層間正交”,使得流量在各個實驗的效果正負抵消,才能得到真實的對比結(jié)果。
以下是計算實驗層桶號的代碼示例,實驗桶號同理:

import com.google.common.hash.Hashing;
import java.nio.charset.StandardCharsets;

public class ABTestRouter {

    /**
     * 根據(jù)用戶ID和實驗層ID(實驗層ID充當(dāng)鹽的角色),計算桶號 (0-99)
     */
    public static int getBucket(String userId, String layerId) {
        // 1. 拼接 Key: "layerId:userId"
        String key = layerId + ":" + userId;

        // 2. 使用 MurmurHash3 (32-bit)
        // Guava 的 murmur3_32_fixed 是線程安全的
        int hash = Hashing.murmur3_32_fixed()
                .hashString(key, StandardCharsets.UTF_8)
                .asInt();

        // 3. 取模并確保結(jié)果為正數(shù)
        // Math.abs(Integer.MIN_VALUE) 會返回負數(shù),所以推薦使用位運算去除符號位
        return (hash & Integer.MAX_VALUE) % 100;
    }

    public static void main(String[] args) {
        String uid = "user_123456";
        
        // 不同層的流量是正交的(打散重新分配)
        System.out.println("展示層桶號: " + getBucket(uid, "layer_ui"));
        System.out.println("算法層桶號: " + getBucket(uid, "layer_algo"));
    }
}

之所以用murmurhash,而非md5,是因為md5是加密算法,計算開銷更大,在AB實驗中僅需均勻打散即可,無需擔(dān)心根據(jù)哈希結(jié)果反推原文。
之所以把實驗層id作為鹽,是因為微小的輸入差異都會導(dǎo)致哈希結(jié)果相差巨大,實現(xiàn)打散的效果。

實驗數(shù)據(jù)收集

實驗數(shù)據(jù)收集流程如下:

  • 在AB實驗管理系統(tǒng)中配置實驗信息:如實驗鹽值、桶號與實驗組的映射關(guān)系等,可動態(tài)修改
  • 代碼邏輯開發(fā):
    • 引入實驗sdk,sdk在啟動、或配置變更時拉取實驗信息,本地計算業(yè)務(wù)id的桶號,進而得到命中的分組
    • 對照組做當(dāng)前邏輯,實驗組1做邏輯1,實驗組2做邏輯2
  • 在正式開始AB實驗之前,先做AA分桶實驗,模擬實驗組、對照組的結(jié)果,判斷是否均勻,避免分桶不均勻帶來錯誤的實驗結(jié)果
  • 實驗開始,后端埋點:sdk發(fā)出后端埋點消息
    • 消息格式舉例:業(yè)務(wù)id, 實驗層id, 實驗id, 分組id, 桶號, 觸發(fā)時間
  • 實驗過程:實驗持續(xù)時間至少一周,覆蓋工作日、周末/假期,避免受時間周期帶來的波動影響
  • 離線統(tǒng)計實驗效果:
    • 后端埋點數(shù)據(jù)導(dǎo)入曝光事件hive表
    • 業(yè)務(wù)DB數(shù)據(jù)導(dǎo)入行為事件hive表,如注冊、登錄、瀏覽、點擊、收藏、加購、下單、支付等,取決于實驗關(guān)注的業(yè)務(wù)指標
    • 把曝光事件、行為事件join起來,對比實驗組、對照組的業(yè)務(wù)指標差異
image.png

以下是sql示例,代表從實驗曝光后24小時內(nèi)各個分組的轉(zhuǎn)化率對比。

SELECT 
    e.group_id,
    COUNT(DISTINCT e.user_id) as exposed_users,
    COUNT(DISTINCT a.user_id) as converted_users,
    COUNT(DISTINCT a.user_id) / COUNT(DISTINCT e.user_id) as conversion_rate
FROM exposure_events e
LEFT JOIN action_events a ON e.user_id = a.user_id 
    AND a.event_time BETWEEN e.event_time AND (e.event_time + INTERVAL 24 HOUR)
WHERE e.experiment_id = 'ui_test_001'
GROUP BY e.group_id;

實驗報表分析

評估實驗結(jié)果是否正向、是否顯著。了解統(tǒng)計學(xué)里的核心概念,能看懂實驗報表即可。

p值

用來衡量實驗結(jié)果是否顯著,p值的含義是:假設(shè)實驗組與對照組沒有區(qū)別,此時觀察到實驗有差異的概率。一般要求 p < 0.05,也就是說實驗結(jié)果顯著的概率大于95%(1 - 0.05 = 95%

置信區(qū)間

在顯著的前提下,用來衡量實驗結(jié)果是否正向,代表業(yè)務(wù)指標的可能范圍分布。
比如:實驗結(jié)果里業(yè)務(wù)指標提升了1%,95%置信區(qū)間在[0.8%, 1.2%],則代表有95%的把握可以把業(yè)務(wù)指標提升至少0.8%、至多1.2%,效果正向。如果置信區(qū)間的下界是負數(shù),就有可能是負向效果了,需要警惕。

以上就是灰度方案的總結(jié)了,歡迎討論交流。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容