費(fèi)系統(tǒng)原理:從費(fèi)率表到模板化計(jì)費(fèi)的演進(jìn)與避坑)
簡(jiǎn)介這份文檔面向電信運(yùn)營(yíng)商業(yè)務(wù)支撐系統(tǒng)的運(yùn)營(yíng)管理與設(shè)計(jì)人員以及希望理解在線計(jì)費(fèi)機(jī)制的技術(shù)學(xué)習(xí)者系統(tǒng)講解OCS在線計(jì)費(fèi)系統(tǒng)的計(jì)費(fèi)原理與實(shí)現(xiàn)路徑幫助讀者厘清實(shí)時(shí)計(jì)費(fèi)從概念到落地的關(guān)鍵環(huán)節(jié)。資源包內(nèi)共1個(gè)doc文件約1.87MB內(nèi)容按序篇、掃盲篇、計(jì)費(fèi)流程等模塊組織涵蓋計(jì)費(fèi)系統(tǒng)從離線批處理向?qū)崟r(shí)處理演進(jìn)的背景TAG、業(yè)務(wù)用量、費(fèi)用項(xiàng)、產(chǎn)品、訂購、入帳關(guān)系、模板、策略、事件與子事件等名詞解釋以及預(yù)處理、批價(jià)等流程拆解并延伸至計(jì)費(fèi)引擎、數(shù)據(jù)庫、消息中間件等實(shí)現(xiàn)組件與安全機(jī)制。已有297人學(xué)習(xí)適合作為理解OCS工作流程、優(yōu)化計(jì)費(fèi)流程與系統(tǒng)設(shè)計(jì)的參考材料。1. 一次通話還沒掛斷錢就已經(jīng)扣完了OCS 到底在背后做了什么你打完一通電話掛機(jī)短信還沒到余額已經(jīng)變了。這個(gè)“實(shí)時(shí)”背后并不是簡(jiǎn)單的“通話結(jié)束扣錢”而是一套在線計(jì)費(fèi)系統(tǒng)在通話進(jìn)行中反復(fù)做預(yù)算、授權(quán)、再預(yù)算的循環(huán)。OCSOnline Charging System在線計(jì)費(fèi)系統(tǒng)要解決的核心問題只有一個(gè)在用戶還沒消費(fèi)完之前就判斷他還能消費(fèi)多少并且保證最終扣的錢和實(shí)際用量對(duì)得上。這件事聽起來簡(jiǎn)單做起來卻牽扯到業(yè)務(wù)用量怎么抽象、費(fèi)用項(xiàng)怎么組織、定價(jià)計(jì)劃怎么復(fù)用、預(yù)付費(fèi)和后付費(fèi)怎么統(tǒng)一。搞懂 OCS 的計(jì)費(fèi)原理本質(zhì)上是在搞懂一套“先授權(quán)后結(jié)算”的信用控制機(jī)制為什么能在線跑起來以及它的抽象層次是怎么一步步演進(jìn)出來的。這份資料把計(jì)費(fèi)系統(tǒng)從兩張表到 OCS 的演進(jìn)拆得很細(xì)下面按機(jī)制層次往下推。2. 計(jì)費(fèi)系統(tǒng)的四次演進(jìn)為什么費(fèi)率表最后一定會(huì)失控2.1 從兩張表到號(hào)碼分析維度爆炸是怎么發(fā)生的最早的計(jì)費(fèi)系統(tǒng)只有兩張表用戶表存余額費(fèi)率表根據(jù)主被叫歸屬地、主被叫拜訪地四個(gè)號(hào)碼頭查費(fèi)率。這個(gè)設(shè)計(jì)在只有一個(gè)號(hào)段、一個(gè)地區(qū)的時(shí)候完全夠用。問題出在號(hào)段增長(zhǎng)之后一個(gè)地區(qū)會(huì)有多個(gè)號(hào)段四個(gè)維度組合在一起費(fèi)率表的記錄數(shù)不是線性增長(zhǎng)而是按維度乘積膨脹。更麻煩的是局方調(diào)整費(fèi)率時(shí)需要人工分析每個(gè)受影響地區(qū)的每一條記錄改錯(cuò)一條就是計(jì)費(fèi)事故。常見的實(shí)現(xiàn)思路是把“查費(fèi)率”拆成三步。第一步號(hào)碼分析把主被叫的歸屬地、拜訪地號(hào)碼頭歸一成地區(qū)號(hào)一個(gè)地區(qū)的多個(gè)號(hào)段在號(hào)碼分析表里收斂成一條記錄。第二步計(jì)費(fèi)矩陣把一次呼叫拆成基本費(fèi)、漫游費(fèi)、長(zhǎng)途費(fèi)三種消費(fèi)類別每個(gè)類別對(duì)應(yīng)一個(gè)費(fèi)率索引也就是 ChargeClass根據(jù)地區(qū)號(hào)查出該用哪組費(fèi)率。第三步才是費(fèi)率表只描述費(fèi)率本身被計(jì)費(fèi)矩陣引用。這樣改費(fèi)率只動(dòng)費(fèi)率表幾條記錄加號(hào)段只動(dòng)號(hào)碼分析表可維護(hù)性從“改一處牽全身”變成“各管各的”。這個(gè)拆分的關(guān)鍵在于把“維度”和“價(jià)格”解耦。號(hào)碼分析負(fù)責(zé)維度歸一計(jì)費(fèi)矩陣負(fù)責(zé)消費(fèi)分類費(fèi)率表負(fù)責(zé)價(jià)格數(shù)值。三層各司其職任何一層的變更不會(huì)污染另外兩層。我一般會(huì)這么理解這不是簡(jiǎn)單的表拆分而是把計(jì)費(fèi)查詢從“一次多維匹配”改成了“三次單維查找”用查詢次數(shù)換維護(hù)性。2.2 帳戶抽象與消費(fèi)類別擴(kuò)展??顚dN為什么需要獨(dú)立帳戶用戶數(shù)增長(zhǎng)之后運(yùn)營(yíng)商發(fā)現(xiàn)單純降價(jià)拉不動(dòng)消費(fèi)于是開始做套餐50 元買 500 分鐘長(zhǎng)途、10 元買 200 分鐘市話長(zhǎng)途時(shí)長(zhǎng)只能打長(zhǎng)途市話時(shí)長(zhǎng)只能打市話用完再走基本余額。這就引出一個(gè)新問題余額不再是單一數(shù)字而是分類型、分用途的多個(gè)池子。實(shí)現(xiàn)上的做法是把余額從用戶表里抽出來單獨(dú)建帳戶表一個(gè)用戶可以掛多個(gè)帳戶每個(gè)帳戶有類型和余額。同時(shí)把 ChargeClass 從純粹的費(fèi)率索引擴(kuò)展成“消費(fèi)類別”額外定義這個(gè)類別只能在哪些帳戶上扣、扣減優(yōu)先級(jí)是什么、費(fèi)率是多少。比如長(zhǎng)途呼叫產(chǎn)生的消費(fèi)類別只能從長(zhǎng)途免費(fèi)時(shí)長(zhǎng)、贈(zèng)送金額、基本金額里按優(yōu)先級(jí)依次扣。這里的設(shè)計(jì)動(dòng)機(jī)是消費(fèi)類別是“怎么算錢”帳戶是“從哪扣錢”兩者通過入帳關(guān)系連接。入帳關(guān)系是一張映射表說明某類費(fèi)用項(xiàng)應(yīng)該落到哪個(gè)帳戶。把“算”和“扣”分開之后??顚dN不需要改計(jì)費(fèi)邏輯只需要配一條入帳關(guān)系。費(fèi)率表也在這個(gè)階段從單一費(fèi)率擴(kuò)展成分檔費(fèi)率頭 3 分鐘一個(gè)價(jià)、后 10 分鐘一個(gè)價(jià)越打越便宜就是分檔費(fèi)率加累計(jì)用量判斷。2.3 OCS 時(shí)代的五個(gè)抽象業(yè)務(wù)用量、計(jì)費(fèi)事件、模板、定價(jià)計(jì)劃、訂購到了多業(yè)務(wù)場(chǎng)景前面那套開始吃力。一次計(jì)費(fèi)請(qǐng)求可能不是“通話 5 分鐘”而是“短信 3 條”“流量 200M”“直接扣款 2 元”用 ChargeClass 加時(shí)長(zhǎng)已經(jīng)表達(dá)不了。套餐推出頻率越來越快改 ChargeClass 既不直觀也容易影響存量業(yè)務(wù)。預(yù)付費(fèi)和后付費(fèi)的計(jì)費(fèi)邏輯被拆在兩套系統(tǒng)里同一個(gè)優(yōu)惠活動(dòng)要配兩遍。OCS 的解法是五個(gè)抽象層層疊加。業(yè)務(wù)用量替代 ChargeClass表達(dá)“消費(fèi)的是什么業(yè)務(wù)、量是多少”比如 20 分鐘長(zhǎng)途費(fèi)、2M 流量新增消費(fèi)類型只是新增一個(gè)用量定義。計(jì)費(fèi)事件把每種計(jì)費(fèi)請(qǐng)求抽象成事件事件包含若干計(jì)費(fèi)要素每個(gè)要素有自己的求解過程新增請(qǐng)求種類是加代碼而不是改老代碼修改是線性的。模板把可復(fù)用的計(jì)費(fèi)能力封裝成模塊贈(zèng)送模板只管贈(zèng)送內(nèi)容參數(shù)呼叫計(jì)費(fèi)模板只管費(fèi)率和適配條件。定價(jià)計(jì)劃是一套完整的費(fèi)用計(jì)算體系包通過調(diào)用多個(gè)模板組合出套餐比如 20 元套餐同時(shí)調(diào)贈(zèng)送模板和呼叫計(jì)費(fèi)模板。訂購決定用戶擁有哪些定價(jià)計(jì)劃只有訂購了才享受對(duì)應(yīng)費(fèi)率。這五層的關(guān)系是事件觸發(fā)計(jì)費(fèi)事件產(chǎn)生業(yè)務(wù)用量定價(jià)計(jì)劃里的模板對(duì)業(yè)務(wù)用量做批價(jià)批價(jià)輸出費(fèi)用項(xiàng)費(fèi)用項(xiàng)按入帳關(guān)系落到帳戶。新增一個(gè)優(yōu)惠活動(dòng)只需要新增一個(gè)定價(jià)計(jì)劃并讓測(cè)試用戶訂購不動(dòng)存量數(shù)據(jù)和代碼可測(cè)試性和兼容性都保住了。2.4 預(yù)付費(fèi)與后付費(fèi)的統(tǒng)一請(qǐng)求用量、授權(quán)用量、已使用用量預(yù)付費(fèi)和后付費(fèi)的本質(zhì)差別在風(fēng)險(xiǎn)控制時(shí)機(jī)預(yù)付費(fèi)先扣錢后消費(fèi)沒有欠費(fèi)風(fēng)險(xiǎn)后付費(fèi)先消費(fèi)后出賬需要賬單、郵寄、催繳。OCS 把計(jì)費(fèi)動(dòng)作統(tǒng)一把差異推到用量類型上。預(yù)付費(fèi)用戶使用前業(yè)務(wù)控制系統(tǒng)發(fā)起計(jì)費(fèi)請(qǐng)求傳入“請(qǐng)求業(yè)務(wù)用量”系統(tǒng)根據(jù)帳戶余額算出“授權(quán)業(yè)務(wù)用量”返回業(yè)務(wù)側(cè)按授權(quán)量控制消費(fèi)。后付費(fèi)用戶使用完成后話單里的實(shí)際用量作為“已使用業(yè)務(wù)用量”送進(jìn)系統(tǒng)批價(jià)入帳。批價(jià)入帳這段邏輯對(duì)兩者完全一致所以定價(jià)計(jì)劃對(duì)預(yù)付費(fèi)和后付費(fèi)都適用。預(yù)付費(fèi)批價(jià)后出話單即可后付費(fèi)再走賬單和催繳那套原有流程。這個(gè)統(tǒng)一還順帶解決了一卡多用。預(yù)付費(fèi)用戶有 10 元A 業(yè)務(wù)請(qǐng)求 5 分鐘需要 1 元系統(tǒng)授權(quán)后還剩 9 元可用B 業(yè)務(wù)同時(shí)請(qǐng)求 200M 流量也能被響應(yīng)不需要等 A 業(yè)務(wù)結(jié)束。因?yàn)槭跈?quán)是在請(qǐng)求時(shí)刻基于當(dāng)前余額算的多個(gè)業(yè)務(wù)可以并發(fā)占用同一份余額的授權(quán)額度只要總額不超。3. 批價(jià)流程拆解從事件到費(fèi)用項(xiàng)鏈表到底經(jīng)過了幾層3.1 預(yù)處理、批價(jià)、入帳、后處理四段的分工一次完整的計(jì)費(fèi)流程分四段。預(yù)處理負(fù)責(zé)把原始計(jì)費(fèi)請(qǐng)求翻譯成系統(tǒng)內(nèi)部能處理的形態(tài)包括解析事件類型、提取計(jì)費(fèi)要素、做必要的格式轉(zhuǎn)換和校驗(yàn)。批價(jià)是核心根據(jù)業(yè)務(wù)用量和定價(jià)計(jì)劃算出費(fèi)用項(xiàng)。入帳根據(jù)入帳關(guān)系把費(fèi)用項(xiàng)落到具體帳戶上完成扣減。后處理做收尾比如生成話單、觸發(fā)通知、更新累計(jì)項(xiàng)。這四段里預(yù)處理和后處理對(duì)初學(xué)者是黑匣子資料里也明確說封裝細(xì)節(jié)只需要知道輸入輸出。真正要理解的是批價(jià)因?yàn)橘M(fèi)率、優(yōu)惠、套餐的所有邏輯都?jí)涸谶@一段。批價(jià)的輸入是業(yè)務(wù)用量集合和用戶訂購的定價(jià)計(jì)劃輸出是費(fèi)用項(xiàng)鏈表。費(fèi)用項(xiàng)鏈表這個(gè)數(shù)據(jù)結(jié)構(gòu)很關(guān)鍵每條記錄包含業(yè)務(wù)用量標(biāo)識(shí)、用量數(shù)值、金額、費(fèi)用項(xiàng)類型鏈表順序?qū)?yīng)消費(fèi)明細(xì)的順序。3.2 業(yè)務(wù)識(shí)別一次呼叫怎么被拆成多個(gè)業(yè)務(wù)用量批價(jià)第一步是業(yè)務(wù)識(shí)別判斷這次計(jì)費(fèi)請(qǐng)求涉及哪些業(yè)務(wù)用量。以主叫漫游撥打長(zhǎng)途 5 分鐘為例系統(tǒng)要判斷主叫是否漫游、被叫是否長(zhǎng)途然后生成基本費(fèi)時(shí)長(zhǎng)、長(zhǎng)途費(fèi)時(shí)長(zhǎng)、漫游費(fèi)時(shí)長(zhǎng)三個(gè)業(yè)務(wù)用量各 300 秒。如果主叫沒有漫游漫游費(fèi)時(shí)長(zhǎng)為 0。這些用量名稱和 TAG 是設(shè)計(jì)時(shí)規(guī)劃好的比如基本費(fèi)時(shí)長(zhǎng)對(duì)應(yīng) TAG 2003長(zhǎng)途費(fèi)時(shí)長(zhǎng)對(duì)應(yīng) 2005漫游費(fèi)時(shí)長(zhǎng)對(duì)應(yīng) 2004。業(yè)務(wù)識(shí)別的本質(zhì)是把“一次呼叫”這個(gè)復(fù)合事件拆成“多個(gè)可獨(dú)立計(jì)價(jià)的用量”。為什么要拆因?yàn)榛举M(fèi)、長(zhǎng)途費(fèi)、漫游費(fèi)可能走不同的費(fèi)率、落不同的帳戶、享受不同的優(yōu)惠。拆成獨(dú)立用量之后每個(gè)用量可以單獨(dú)匹配定價(jià)計(jì)劃里的模板互不干擾。這跟前面說的消費(fèi)類別擴(kuò)展是一脈相承的只是粒度更細(xì)、表達(dá)更通用。3.3 批價(jià)處理與費(fèi)用項(xiàng)生成費(fèi)率匹配和金額計(jì)算怎么落地業(yè)務(wù)用量確定后批價(jià)按用量逐個(gè)匹配定價(jià)計(jì)劃。匹配的依據(jù)是定價(jià)計(jì)劃里模板的適配條件比如“省內(nèi)漫游”這個(gè)條件只對(duì)漫游費(fèi)用量生效。匹配上之后模板用傳入的費(fèi)率參數(shù)對(duì)用量做計(jì)算。假設(shè)市話費(fèi)率 0.1 元/分鐘、長(zhǎng)途 0.2 元/分鐘、漫游 0.3 元/分鐘5 分鐘就是 300 秒三個(gè)用量分別算出 50 分、100 分、150 分生成三條費(fèi)用項(xiàng)本地通話費(fèi)用項(xiàng)、長(zhǎng)途通話費(fèi)用項(xiàng)、漫游通話費(fèi)用項(xiàng)。費(fèi)用項(xiàng)鏈表的結(jié)構(gòu)可以粗略表示為下面這樣字段名按資料里的描述歸納# 費(fèi)用項(xiàng)節(jié)點(diǎn)批價(jià)輸出的消費(fèi)明細(xì)單元 class ChargeItem: def __init__(self, usage_tag, usage_value, amount, item_type): self.usage_tag usage_tag # 業(yè)務(wù)用量標(biāo)識(shí)如 2003 基本費(fèi)時(shí)長(zhǎng) self.usage_value usage_value # 用量數(shù)值如 300 秒 self.amount amount # 金額單位分 self.item_type item_type # 費(fèi)用項(xiàng)類型如 1 本地通話 self.next None # 鏈表指針串起多條消費(fèi)明細(xì) # 批價(jià)主循環(huán)的簡(jiǎn)化邏輯 def rating(usages, pricing_plan): head None for usage in usages: template pricing_plan.match(usage) # 按適配條件匹配模板 if template is None: continue # 無匹配則不產(chǎn)生費(fèi)用項(xiàng) amount template.calculate(usage) # 模板內(nèi)按費(fèi)率算金額 node ChargeItem(usage.tag, usage.value, amount, template.item_type) node.next head # 頭插或尾插形成消費(fèi)清單 head node return head這段邏輯里match負(fù)責(zé)適配條件判斷calculate負(fù)責(zé)費(fèi)率計(jì)算兩者都在模板內(nèi)部批價(jià)主循環(huán)只做遍歷和組裝。這樣新增一種計(jì)費(fèi)能力只需要新增模板主循環(huán)不動(dòng)。usage_tag和item_type的分離也值得注意用量標(biāo)識(shí)說明消費(fèi)了什么費(fèi)用項(xiàng)類型說明這筆錢歸到哪類賬目入帳時(shí)看的是后者。3.4 入帳關(guān)系費(fèi)用項(xiàng)怎么找到該扣的帳戶批價(jià)輸出費(fèi)用項(xiàng)之后入帳按入帳關(guān)系把每條費(fèi)用項(xiàng)映射到帳戶。入帳關(guān)系是一張配置說明某類費(fèi)用項(xiàng)按什么優(yōu)先級(jí)從哪些帳戶扣。比如長(zhǎng)途通話費(fèi)用項(xiàng)先扣長(zhǎng)途免費(fèi)時(shí)長(zhǎng)帳戶扣完再扣贈(zèng)送金額帳戶最后扣基本余額帳戶。每個(gè)帳戶扣減時(shí)還要判斷余額是否足夠不足的部分按優(yōu)先級(jí)繼續(xù)往下找。這里有個(gè)容易忽略的點(diǎn)入帳不是簡(jiǎn)單扣一個(gè)總數(shù)而是按費(fèi)用項(xiàng)逐條處理每條費(fèi)用項(xiàng)獨(dú)立走自己的入帳關(guān)系。這意味著一次呼叫產(chǎn)生的本地、長(zhǎng)途、漫游三條費(fèi)用項(xiàng)可能分別落到三個(gè)不同的帳戶組合上。這種設(shè)計(jì)讓??顚dN和分類型余額能夠精確執(zhí)行代價(jià)是入帳階段要做多次帳戶查找和扣減對(duì)性能有要求。常見的優(yōu)化是把同一用戶的帳戶和入帳關(guān)系做緩存批價(jià)和入帳之間盡量少查庫。4. 充值、月結(jié)與免費(fèi)資源那些不在呼叫主流程里的計(jì)費(fèi)能力4.1 充值流程的預(yù)處理與模板復(fù)用充值看起來是獨(dú)立流程但它復(fù)用了和呼叫計(jì)費(fèi)同一套模板機(jī)制。充值請(qǐng)求進(jìn)來先做預(yù)處理解析充值金額、充值類型、用戶標(biāo)識(shí)然后匹配充值相關(guān)的定價(jià)計(jì)劃。充 100 送 40 分幾個(gè)月贈(zèng)送這種活動(dòng)本質(zhì)是充值模板加贈(zèng)送模板的組合充值模板處理本金入帳贈(zèng)送模板按分期規(guī)則生成后續(xù)的贈(zèng)送計(jì)劃。模板復(fù)用的價(jià)值在這里體現(xiàn)得很明顯。贈(zèng)送能力被封裝成模板之后呼叫套餐里的贈(zèng)送、充值活動(dòng)的贈(zèng)送、月結(jié)的回贈(zèng)調(diào)的都是同一個(gè)模板只是參數(shù)不同。參數(shù)包括贈(zèng)送內(nèi)容、贈(zèng)送時(shí)機(jī)、分期方式。這樣新增一種贈(zèng)送活動(dòng)不需要寫新代碼配參數(shù)就行。資料里把模板和策略并列解釋我理解模板是“計(jì)費(fèi)能力的實(shí)現(xiàn)”策略是“模板被調(diào)用時(shí)的參數(shù)和條件組合”兩者配合才能表達(dá)一個(gè)完整的優(yōu)惠規(guī)則。4.2 月結(jié)與回贈(zèng)定期事務(wù)怎么和實(shí)時(shí)計(jì)費(fèi)共用一套帳戶月結(jié)是定期事務(wù)每天后臺(tái)跑處理月租扣取、套餐定期贈(zèng)送、充值優(yōu)惠分期到賬。它和實(shí)時(shí)計(jì)費(fèi)共用帳戶表和入帳關(guān)系區(qū)別在于觸發(fā)時(shí)機(jī)和用量來源。實(shí)時(shí)計(jì)費(fèi)的用量來自呼叫事件月結(jié)的用量來自時(shí)間周期和預(yù)配的贈(zèng)送計(jì)劃。月結(jié)流程里系統(tǒng)掃描到期的贈(zèng)送計(jì)劃生成對(duì)應(yīng)的業(yè)務(wù)用量走批價(jià)和入帳把贈(zèng)送金額或時(shí)長(zhǎng)落到用戶帳戶?;刭?zèng)是月結(jié)的一個(gè)子場(chǎng)景比如充值送的分月到賬每個(gè)月結(jié)日把當(dāng)月份額入帳。因?yàn)樽叩氖峭惶着鷥r(jià)入帳邏輯月結(jié)贈(zèng)送和呼叫計(jì)費(fèi)在帳戶層面完全一致不會(huì)出現(xiàn)兩套余額對(duì)不上的情況。這也是 OCS 把 iCharge 和 iUser-bill 融合之后的好處定期事務(wù)和實(shí)時(shí)計(jì)費(fèi)不再是兩個(gè)系統(tǒng)而是同一套計(jì)費(fèi)能力的不同觸發(fā)方式。4.3 免費(fèi)資源與累計(jì)項(xiàng)套餐里的“先用免費(fèi)額度”怎么實(shí)現(xiàn)免費(fèi)資源處理是套餐計(jì)費(fèi)里的常見需求用戶訂購了含 300 分鐘市話的套餐打電話時(shí)先扣免費(fèi)時(shí)長(zhǎng)用完再按費(fèi)率扣錢。實(shí)現(xiàn)上免費(fèi)時(shí)長(zhǎng)存在特定類型的帳戶里批價(jià)時(shí)業(yè)務(wù)用量先匹配免費(fèi)資源模板模板判斷對(duì)應(yīng)帳戶是否有余額有則生成金額為 0 的費(fèi)用項(xiàng)并扣減免費(fèi)時(shí)長(zhǎng)沒有則走正常費(fèi)率模板。累計(jì)項(xiàng)處理解決的是“越打越便宜”和“消費(fèi)累計(jì)”這類跨呼叫的狀態(tài)問題。累計(jì)項(xiàng)記錄用戶在某段時(shí)間內(nèi)的累計(jì)用量或累計(jì)消費(fèi)批價(jià)時(shí)讀取累計(jì)項(xiàng)判斷當(dāng)前處于哪個(gè)分檔。比如頭 3 分鐘 0.4 元/分鐘、后 10 分鐘 0.2 元/分鐘批價(jià)時(shí)要先查累計(jì)通話時(shí)長(zhǎng)確定本次用量落在哪一檔再按對(duì)應(yīng)費(fèi)率計(jì)算。累計(jì)項(xiàng)的更新發(fā)生在批價(jià)或后處理階段要保證和費(fèi)用項(xiàng)生成的一致性否則會(huì)出現(xiàn)費(fèi)率跳檔錯(cuò)誤。常見的坑是累計(jì)項(xiàng)更新和批價(jià)不在同一個(gè)事務(wù)里并發(fā)呼叫時(shí)讀到舊值這個(gè)在排查章節(jié)會(huì)展開。5. 避坑與排查OCS 計(jì)費(fèi)里那些容易翻車的地方5.1 費(fèi)用項(xiàng)金額對(duì)但帳戶扣錯(cuò)入帳關(guān)系配反了現(xiàn)象是批價(jià)輸出的費(fèi)用項(xiàng)金額正確但用戶的基本余額沒動(dòng)反而贈(zèng)送帳戶被多扣了。原因通常是入帳關(guān)系里費(fèi)用項(xiàng)類型和帳戶類型的映射配反或者扣減優(yōu)先級(jí)順序?qū)戝e(cuò)。排查時(shí)先看批價(jià)輸出的費(fèi)用項(xiàng)鏈表確認(rèn) item_type 正確再查入帳關(guān)系表里該 item_type 對(duì)應(yīng)的帳戶列表和優(yōu)先級(jí)逐條比對(duì)扣減記錄。解決方法是修正入帳關(guān)系配置并對(duì)已受影響的用戶做余額沖正。5.2 免費(fèi)時(shí)長(zhǎng)沒用完就開始扣錢免費(fèi)資源模板的適配條件沒命中用戶套餐里有 300 分鐘市話但第一通電話就扣了基本余額。原因多半是免費(fèi)資源模板的適配條件沒匹配上比如業(yè)務(wù)用量標(biāo)識(shí)和模板條件里的用量類型不一致或者免費(fèi)帳戶的入帳關(guān)系優(yōu)先級(jí)低于基本余額。排查時(shí)看批價(jià)日志里該次呼叫匹配到了哪些模板如果免費(fèi)資源模板沒出現(xiàn)在匹配列表里就是適配條件問題如果匹配了但沒扣免費(fèi)帳戶就是入帳關(guān)系優(yōu)先級(jí)問題。解決方法是修正模板適配條件或調(diào)整入帳優(yōu)先級(jí)。5.3 并發(fā)呼叫下余額被扣穿授權(quán)和扣減之間的時(shí)間窗預(yù)付費(fèi)用戶同時(shí)發(fā)起兩路呼叫每路都請(qǐng)求授權(quán)系統(tǒng)基于同一份余額分別算出授權(quán)量結(jié)果兩路都授權(quán)成功實(shí)際消費(fèi)超過余額。這是授權(quán)階段的經(jīng)典并發(fā)問題。原因在于授權(quán)時(shí)讀余額和扣減時(shí)讀余額之間有時(shí)間窗兩個(gè)請(qǐng)求都讀到了扣減前的余額。常見的實(shí)現(xiàn)思路是在授權(quán)時(shí)做額度預(yù)占把授權(quán)量對(duì)應(yīng)的金額先凍結(jié)扣減時(shí)用凍結(jié)額度結(jié)算釋放多余部分。排查時(shí)看授權(quán)記錄和扣減記錄的時(shí)間戳確認(rèn)是否存在同一余額被多次授權(quán)。解決方法是引入預(yù)占機(jī)制或?qū)τ脩艏?jí)余額加鎖。5.4 月結(jié)贈(zèng)送沒到賬贈(zèng)送計(jì)劃的到期判斷用了錯(cuò)誤時(shí)區(qū)月結(jié)跑完之后部分用戶的充值贈(zèng)送沒有入帳。原因可能是贈(zèng)送計(jì)劃的到期時(shí)間按 UTC 存儲(chǔ)月結(jié)任務(wù)按本地時(shí)間判斷到期跨時(shí)區(qū)時(shí)差導(dǎo)致部分計(jì)劃被跳過。排查時(shí)對(duì)比贈(zèng)送計(jì)劃的到期時(shí)間字段和月結(jié)任務(wù)的判斷條件看時(shí)間基準(zhǔn)是否一致。解決方法是統(tǒng)一時(shí)間基準(zhǔn)或者在月結(jié)任務(wù)里顯式做時(shí)區(qū)轉(zhuǎn)換。這類問題在跨地區(qū)部署時(shí)特別容易翻車血淚經(jīng)驗(yàn)是時(shí)間字段一定要標(biāo)注時(shí)區(qū)。5.5 累計(jì)項(xiàng)跳檔錯(cuò)誤批價(jià)和累計(jì)更新不在同一事務(wù)越打越便宜的套餐用戶反映費(fèi)率跳檔不對(duì)有時(shí)提前跳檔有時(shí)延遲跳檔。原因是累計(jì)項(xiàng)更新和批價(jià)計(jì)算不在同一個(gè)事務(wù)里并發(fā)呼叫時(shí)批價(jià)讀到的累計(jì)值是舊的算完費(fèi)率后另一個(gè)呼叫又更新了累計(jì)項(xiàng)導(dǎo)致分檔判斷錯(cuò)位。排查時(shí)看同一用戶短時(shí)間內(nèi)的多次批價(jià)記錄對(duì)比每次讀到的累計(jì)值和實(shí)際累計(jì)值。解決方法是將累計(jì)項(xiàng)讀取、批價(jià)、累計(jì)項(xiàng)更新放在同一事務(wù)或同一把用戶級(jí)鎖內(nèi)保證讀到的累計(jì)值和更新之間沒有其他寫入。6. 抽象層次的取舍為什么 OCS 選擇用模板和定價(jià)計(jì)劃換靈活性回頭看這四次演進(jìn)每一次都是在解決上一階段的抽象泄漏。兩張表階段費(fèi)率和維度混在一起加號(hào)段就爆炸號(hào)碼分析加計(jì)費(fèi)矩陣階段維度和價(jià)格分開了但消費(fèi)類型和帳戶還是硬編碼帳戶抽象階段??顚dN能做了但多業(yè)務(wù)和多計(jì)費(fèi)單位表達(dá)不了OCS 階段用業(yè)務(wù)用量、計(jì)費(fèi)事件、模板、定價(jià)計(jì)劃、訂購五層抽象把“算什么”“怎么算”“從哪扣”“誰能享受”徹底拆開。這個(gè)拆分的代價(jià)是抽象層數(shù)變多初學(xué)者容易在模板和定價(jià)計(jì)劃之間迷路。資料里也承認(rèn) OCS 概念抽象、細(xì)節(jié)暴露多、版本里揉成一團(tuán)。但從設(shè)計(jì)取舍看這是用前期理解成本換后期的擴(kuò)展性新增業(yè)務(wù)類型加事件新增計(jì)費(fèi)能力加模板新增優(yōu)惠活動(dòng)加定價(jià)計(jì)劃新增用戶群加訂購每一層的變化都被限制在自己的邊界內(nèi)。對(duì)比智能網(wǎng)時(shí)代改 ChargeClass 牽一發(fā)動(dòng)全身OCS 的線性修改特性是它能在多業(yè)務(wù)場(chǎng)景下站住腳的根本原因。驗(yàn)證這套機(jī)制是否理解到位有個(gè)簡(jiǎn)單方法拿一個(gè)具體套餐比如“20 元套餐贈(zèng)送 300 分鐘市話、200 條網(wǎng)內(nèi)短信、省內(nèi)漫游 0.1 元/分鐘”從訂購開始往下推看它調(diào)了哪些模板、生成了哪些業(yè)務(wù)用量、批價(jià)輸出哪些費(fèi)用項(xiàng)、按什么入帳關(guān)系落到哪些帳戶。能把這整條鏈路推通說明抽象層次和實(shí)現(xiàn)細(xì)節(jié)都對(duì)上了。我一般排查計(jì)費(fèi)問題時(shí)也強(qiáng)制走一遍這個(gè)鏈路從費(fèi)用項(xiàng)反推到業(yè)務(wù)用量再反推到事件和定價(jià)計(jì)劃比直接看代碼快得多。這份資料把掃盲、入門、提高三篇的層次鋪得很清楚配合實(shí)際配置數(shù)據(jù)看能把 OCS 的計(jì)費(fèi)原理從概念落到可操作的細(xì)節(jié)上。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取