:元模型、編碼與拓撲數(shù)據(jù)可信設(shè)計)
簡介《中國移動綜合網(wǎng)絡(luò)資源管理系統(tǒng)技術(shù)規(guī)范 通用功能分冊》是一份面向通信運營商網(wǎng)絡(luò)資源管理、運維支撐及系統(tǒng)建設(shè)人員的企標文檔適合需要理解綜合網(wǎng)管系統(tǒng)功能邊界、開展資源模型設(shè)計與平臺實施的技術(shù)人員參考。文檔圍繞系統(tǒng)定位、總體目標與建設(shè)原則展開重點說明資源模型管理、命名管理、數(shù)據(jù)質(zhì)量管理、批量導(dǎo)入導(dǎo)出與系統(tǒng)管理工具等基礎(chǔ)維護能力并覆蓋空間、物理、邏輯、業(yè)務(wù)資源及資源拓撲的存量管理以及調(diào)配、分析、展現(xiàn)等應(yīng)用功能和數(shù)據(jù)共享服務(wù)同時給出流程、接口、可用性等技術(shù)功能要求。壓縮包內(nèi)共1個doc文件約1.03MB目錄層級完整便于按章節(jié)檢索。已有306人學(xué)習(xí)可作為方案編制、需求梳理和系統(tǒng)設(shè)計時的對照材料。1. 資源管理系統(tǒng)的悖論調(diào)度算法不難難的是“數(shù)據(jù)敢不敢信”很多團隊接到綜合網(wǎng)絡(luò)資源管理系統(tǒng)的建設(shè)任務(wù)第一反應(yīng)是研究調(diào)度算法、拓撲尋路、GIS 渲染。真正上線后翻車的往往不是這些服務(wù)開通工單卡住查出來是兩臺設(shè)備在資源庫里掛了同一個編碼故障定位派錯班組原因是機房和基站的從屬關(guān)系在三個月前的一次割接里被改丟了。資源數(shù)據(jù)一旦成為服務(wù)開通、故障支撐、備品備件、資產(chǎn)管理的共享底座任何一處不一致都會被下游放大。這也是為什么一份通用功能分冊會把大半篇幅壓在資源模型、命名規(guī)則、數(shù)據(jù)質(zhì)量、資源機歷這些“不性感”的地基上——它們決定的是系統(tǒng)上限。把這幾塊機制吃透再看功能列表很多設(shè)計就順了。2. 資源模型與命名為什么“先建模再入庫”繞不過去2.1 資源模板把“類型”當(dāng)成數(shù)據(jù)而不是代碼通信資源的種類多到超出直覺??臻g資源里有行政區(qū)劃、局站、機房、基站、用戶接入點物理資源里有網(wǎng)絡(luò)設(shè)備、連接設(shè)備、無線設(shè)施、光纜、電纜、管道、桿路邏輯資源里有電路、時隙、邏輯端口、拓撲連接、碼號與地址段業(yè)務(wù)資源還要跟產(chǎn)品、客戶掛上關(guān)系。如果每一類資源建一張物理表、寫一套增刪改查表數(shù)量會迅速失控更麻煩的是新增一種資源類型就要改庫表、改代碼、發(fā)版建設(shè)周期根本扛不住。規(guī)范里給出的答案是“資源模板”把資源通用的規(guī)則、屬性抽出來單獨定義形成實體的模板事先定義好類型信息和實例之間的嵌套、連接配置規(guī)則入庫時只做參數(shù)化配置就能批量形成資源實例。翻譯成實現(xiàn)語言就是元模型驅(qū)動——類型、屬性、關(guān)系本身都是數(shù)據(jù)實例只是按模板填參數(shù)。簡化后的元模型一般長這樣-- 資源類型定義描述“有哪幾類資源”支持繼承 CREATE TABLE res_type ( type_id VARCHAR(32) PRIMARY KEY, -- 類型編碼如 PHYS_CABLE type_name VARCHAR(64) NOT NULL, -- 類型名稱如 光纜段 parent_type VARCHAR(32), -- 父類型實現(xiàn)屬性繼承 is_abstract SMALLINT DEFAULT 0 -- 抽象類型不可直接實例化 ); -- 屬性定義描述“這類資源有哪些字段” CREATE TABLE res_attr_def ( attr_id BIGINT PRIMARY KEY, type_id VARCHAR(32) NOT NULL, -- 歸屬類型 attr_code VARCHAR(64) NOT NULL, -- 屬性編碼 data_type VARCHAR(16) NOT NULL, -- STRING/NUMBER/DATE/ENUM is_required SMALLINT DEFAULT 0, -- 是否必填入庫校驗用 enum_source VARCHAR(128) -- 枚舉值來源數(shù)據(jù)字典 );這兩張表的意義在于新增“光纜段”這種資源不需要改表結(jié)構(gòu)往res_type插一行、往res_attr_def插若干行屬性定義即可實例數(shù)據(jù)落在統(tǒng)一的實例表里專有屬性走擴展屬性表或文檔字段。is_abstract防止把“物理資源”這種抽象父類直接實例化parent_type讓子類型自動繼承父類型的公共屬性避免每類資源重復(fù)定義“名稱、編碼、狀態(tài)、所屬區(qū)域”這些字段。常見的實現(xiàn)思路是“主表存公共屬性、擴展表存專有屬性”。主表字段固定、索引好建適合高頻查詢擴展表按(res_id, attr_code, attr_value)存靈活但查詢要行轉(zhuǎn)列。兩條路都有代價后文會講取舍。2.2 命名與編碼唯一標識一旦漂移下游全斷資源模型解決“長什么樣”命名編碼解決“怎么認”??缦到y(tǒng)共享時服務(wù)開通系統(tǒng)、故障支撐系統(tǒng)、備品備件系統(tǒng)都靠編碼對齊同一個資源編碼不統(tǒng)一共享服務(wù)就退化成人肉對賬。規(guī)范把命名拆成“規(guī)則接收、名稱生成、編碼管理”幾塊。落到實現(xiàn)命名規(guī)則通常要同時滿足四個約束全局唯一、可解析、穩(wěn)定、可擴展。可解析意味著從編碼能讀出歸屬區(qū)域、專業(yè)、類型方便分庫分表和權(quán)限隔離穩(wěn)定意味著編碼一旦生成不隨資源改名、遷移、歸屬調(diào)整而變化可擴展意味著新專業(yè)、新類型加入時不會和存量編碼沖突。常見的分段編碼結(jié)構(gòu)如下| 段名 | 長度 | 示例 | 說明 | | 區(qū)域碼 | 6 | 310000 | 行政區(qū)劃或管理區(qū)域 | | 專業(yè)碼 | 2 | 01 | 傳輸、無線、數(shù)據(jù)等 | | 類型碼 | 3 | 002 | 光纜、機房、設(shè)備等 | | 序列號 | 9 | 000012345 | 按類型遞增 |這套結(jié)構(gòu)可讀性好但有個血淚經(jīng)驗行政區(qū)劃調(diào)整、專業(yè)重組時區(qū)域碼和專業(yè)碼的語義會漂移如果下游把它當(dāng)業(yè)務(wù)屬性用就會出現(xiàn)“編碼還指著舊區(qū)域”的尷尬。更穩(wěn)的做法是雙軌內(nèi)部主鍵用無業(yè)務(wù)含義的全局 ID雪花 ID 或 UUID外部業(yè)務(wù)編碼單獨一列并加唯一約束共享接口只暴露業(yè)務(wù)編碼內(nèi)部關(guān)聯(lián)走主鍵。這樣即便編碼規(guī)則升級歷史關(guān)聯(lián)也不會斷。命名規(guī)則還要處理“重名”和“預(yù)留”。同一機房內(nèi)兩臺設(shè)備名稱相同是常態(tài)靠編碼區(qū)分碼號、地址段這類資源還要支持分段拆分合并編碼生成時要檢查父子段關(guān)系避免把已經(jīng)分配出去的地址段再切一次。注意編碼一旦發(fā)給下游系統(tǒng)使用就成了事實上的外部契約。改編碼規(guī)則之前先跑一遍影響面比事后修數(shù)據(jù)便宜得多。3. 存量管理的四層結(jié)構(gòu)空間、物理、邏輯、業(yè)務(wù)怎么拆3.1 分層依據(jù)按“承載關(guān)系”切而不是按“專業(yè)”切規(guī)范把資源分成空間、物理、邏輯、業(yè)務(wù)四層。這個分法容易被誤解成“按專業(yè)分類”其實底層依據(jù)是承載關(guān)系業(yè)務(wù)資源承載在邏輯資源上邏輯資源承載在物理資源上物理資源安裝在空間資源里。一條客戶專線業(yè)務(wù)對應(yīng)一條電路邏輯電路落在兩端設(shè)備的端口和中間的傳輸系統(tǒng)上物理設(shè)備又裝在機房空間。每層只關(guān)心自己這層的屬性和上下層關(guān)系不把全部屬性塞進一張大表。這樣切的好處很直接新增一種無線設(shè)備只影響物理層的類型定義新增一種業(yè)務(wù)套餐只影響業(yè)務(wù)層空間層幾乎不動。反過來如果按專業(yè)建表傳輸、無線、數(shù)據(jù)各搞一套跨專業(yè)的端到端路由查詢就要寫一堆適配代碼。實例化路徑是“模板 → 實例 → 關(guān)系”。以光纜段為例模板定義起點、終點、芯數(shù)、長度、敷設(shè)方式入庫時填參數(shù)生成實例同時自動建立三類關(guān)系兩端連接的空間資源局站/人井、兩端連接的物理資源ODF 架/設(shè)備端口、以及它與父纜的從屬關(guān)系。批量導(dǎo)入時按模板做字段校驗和關(guān)系校驗校驗不過的行整批回滾避免半截數(shù)據(jù)入庫。邏輯資源里有一類特殊的東西——碼號與地址段。它們沒有物理形態(tài)但有分配和回收的生命周期還要支持拆分合并。規(guī)范把碼號/IP 地址管理放進資源應(yīng)用層正是因為這類資源的“管理”更多是分配策略和沖突檢測而不是簡單的增刪改查。3.2 拓撲與機歷關(guān)系數(shù)據(jù)和時序數(shù)據(jù)是兩個獨立問題拓撲解決“誰連著誰”。資源之間的連接關(guān)系是多對多、有類型、有時效的塞進資源主表當(dāng)外鍵會很難受。常見做法是獨立的關(guān)系表至少包含源資源、目標資源、關(guān)系類型、方向、生效與失效時間。物理連接纜線兩端、邏輯連接中繼、傳輸電路、承載關(guān)系業(yè)務(wù)掛邏輯、邏輯掛物理都走這張表靠關(guān)系類型區(qū)分。CREATE TABLE res_relation ( rel_id BIGINT PRIMARY KEY, src_res_id VARCHAR(64) NOT NULL, -- 源資源 dst_res_id VARCHAR(64) NOT NULL, -- 目標資源 rel_type VARCHAR(32) NOT NULL, -- PHYS_LINK/LOGIC_LINK/BEAR/INSTALL direction SMALLINT DEFAULT 0, -- 0無向 1單向 valid_from TIMESTAMP, -- 生效時間 valid_to TIMESTAMP -- 失效時間NULL表示當(dāng)前有效 );獨立關(guān)系表的最大風(fēng)險是懸空資源退網(wǎng)了關(guān)系還在拓撲圖上就會出現(xiàn)指向空氣的連線。所以退網(wǎng)建議走狀態(tài)標記而不是物理刪除同時定期跑關(guān)系完整性校驗——兩端資源必須存在且狀態(tài)有效否則告警。這個校驗看著笨卻是拓撲可信度的底線。機歷解決“怎么變成現(xiàn)在這樣”。資源從入庫、調(diào)整、割接到退網(wǎng)每一次變更都應(yīng)該留痕。規(guī)范里叫資源機歷卡支持記錄、呈現(xiàn)、定制和清除。實現(xiàn)上一般是當(dāng)前表加歷史表或者事件溯源每次變更寫一條事件記錄變更類型、變更前后快照、關(guān)聯(lián)工單號。CREATE TABLE res_history ( hist_id BIGINT PRIMARY KEY, res_id VARCHAR(64) NOT NULL, change_time TIMESTAMP NOT NULL, change_type VARCHAR(16) NOT NULL, -- CREATE/UPDATE/CUTOVER/DELETE before_json TEXT, -- 變更前快照便于回放 after_json TEXT, -- 變更后快照 order_id VARCHAR(64) -- 關(guān)聯(lián)工單審計用 );before_json和after_json的價值在故障回溯三個月前某臺設(shè)備的位置被改過導(dǎo)致派單派錯機歷一拉就能看到是誰、在哪個工單里改的。order_id把資源變更和流程綁定避免“數(shù)據(jù)變了但沒人認賬”。機歷的代價是存儲和寫入放大所以常見策略是只對關(guān)鍵字段做快照非關(guān)鍵字段記變更摘要歷史數(shù)據(jù)按時間分區(qū)超過保留期的歸檔。4. 資源應(yīng)用層調(diào)度是一個狀態(tài)機不是一次數(shù)據(jù)庫更新4.1 配置與調(diào)度的狀態(tài)流轉(zhuǎn)資源應(yīng)用層里最容易寫歪的是調(diào)度。規(guī)范描述得很清楚針對客戶業(yè)務(wù)、網(wǎng)絡(luò)優(yōu)化調(diào)整、網(wǎng)絡(luò)建設(shè)、網(wǎng)絡(luò)保障發(fā)起的資源請求完成從資源方案設(shè)計、施工任務(wù)指派、聯(lián)調(diào)測試到資源報竣的業(yè)務(wù)實現(xiàn)過程。這句話的重點是“過程”——它不是一次把資源狀態(tài)改成占用而是一串有先后依賴的狀態(tài)遷移。典型狀態(tài)機大致是請求受理 → 資源查勘 → 方案設(shè)計 → 方案審核 → 任務(wù)指派 → 施工中 → 聯(lián)調(diào) → 報竣 → 歸檔。每個狀態(tài)下資源本身還有一套狀態(tài)位空閑、預(yù)占、占用、故障、退網(wǎng)。方案審核通過時把資源置為預(yù)占施工完成報竣后置為占用退網(wǎng)工單走退網(wǎng)。| 當(dāng)前狀態(tài) | 觸發(fā)事件 | 下一狀態(tài) | 關(guān)鍵約束 | | 空閑 | 方案審核通過 | 預(yù)占 | 必須帶過期時間 | | 預(yù)占 | 施工完成并報竣 | 占用 | 寫機歷、關(guān)聯(lián)工單 | | 預(yù)占 | 超過 TTL 未施工 | 空閑 | 自動釋放記異常 | | 占用 | 退網(wǎng)工單完成 | 退網(wǎng) | 保留歷史不物理刪除 |預(yù)占必須帶 TTL這是踩坑高發(fā)區(qū)。工單卡在某個環(huán)節(jié)沒人處理資源一直預(yù)占別的工單查不到可用資源最后變成“系統(tǒng)里明明有空閑端口卻分配不出去”的玄學(xué)。自動釋放加異常記錄比人工巡檢靠譜。并發(fā)控制也要在這一層做。兩個工單同時給同一個端口做方案都查到“空閑”都寫預(yù)占后寫的覆蓋先寫的。常見做法是資源狀態(tài)位加版本號做樂觀鎖更新時帶where statusIDLE and version?影響行數(shù)為零就重試或報沖突。4.2 割接與預(yù)警影響范圍分析是圖遍歷封鎖是原子操作割接是資源系統(tǒng)里風(fēng)險最高的動作。規(guī)范把割接流程拆成待割接資源識別、影響范圍分析、資源封鎖、割接資料入庫、數(shù)據(jù)發(fā)布、解封鎖幾個環(huán)節(jié)。影響范圍分析的本質(zhì)是沿拓撲做遍歷從割接資源出發(fā)向下游找承載的業(yè)務(wù)資源向上游找依賴的客戶和產(chǎn)品把受影響的清單拉出來。def impact_scope(res_id, graph, max_depth8): 沿承載關(guān)系向下游遍歷收集受影響的業(yè)務(wù)資源。 graph: 鄰接表key 為資源 IDvalue 為下游資源列表 max_depth: 限制深度防止超大網(wǎng)絡(luò)遍歷拖垮內(nèi)存 visited, queue, affected {res_id}, [(res_id, 0)], [] while queue: cur, depth queue.pop(0) if depth max_depth: continue for nxt in graph.get(cur, []): if nxt in visited: continue # 防止環(huán)導(dǎo)致死循環(huán) visited.add(nxt) if is_service_resource(nxt): affected.append(nxt) # 命中業(yè)務(wù)層即記錄 else: queue.append((nxt, depth 1)) return affected這段遍歷有幾個參數(shù)值得說graph是關(guān)系表在內(nèi)存里的鄰接表投影只保留“承載”方向避免把上游容器也算進影響范圍visited防環(huán)通信網(wǎng)絡(luò)里環(huán)路不少max_depth是保護全圖遍歷在省級網(wǎng)絡(luò)規(guī)模下可能幾十萬節(jié)點不限制深度容易把接口拖超時。真要做全量影響分析一般是離線跑批加緩存而不是在割接工單里同步算。封鎖是另一個關(guān)鍵點。影響范圍算出來后要把相關(guān)資源置為封鎖態(tài)防止割接期間被調(diào)度工單搶走。封鎖必須是原子操作批量置狀態(tài)要么全成功要么全失敗否則會出現(xiàn)“一半資源鎖了、一半沒鎖”的中間態(tài)割接做到一半發(fā)現(xiàn)端口被占用。常見實現(xiàn)是數(shù)據(jù)庫事務(wù)加狀態(tài)前置校驗失敗回滾并給出沖突清單。預(yù)警則相對獨立規(guī)則管理利用率、年限、故障率、性能閾值、數(shù)據(jù)監(jiān)控、通知。它的技術(shù)難點不在規(guī)則本身而在數(shù)據(jù)時效——預(yù)警跑的是存量數(shù)據(jù)的聚合如果資源數(shù)據(jù)本身滯后預(yù)警就是馬后炮。5. 常見排查資源數(shù)據(jù)不一致的五種現(xiàn)場5.1 批量導(dǎo)入成功但大量屬性為空現(xiàn)象導(dǎo)入回執(zhí)顯示成功打開資源詳情發(fā)現(xiàn)必填屬性是空值或默認值。原因通常有兩個導(dǎo)入模板版本和資源模型版本不一致模板里少了幾列或者模型里字段被改成必填但導(dǎo)入校驗沒同步。解決思路是把模板和模型版本綁定導(dǎo)入前先做版本比對導(dǎo)入后跑一遍必填項校驗報告校驗不通過的行整批回滾不要留半截數(shù)據(jù)。5.2 同一臺設(shè)備在不同系統(tǒng)編碼對不上現(xiàn)象服務(wù)開通系統(tǒng)按編碼查不到故障支撐系統(tǒng)里的同一臺設(shè)備人工核對發(fā)現(xiàn)是同一臺。原因多半是編碼由各系統(tǒng)各自生成命名規(guī)則沒統(tǒng)一或者規(guī)則升級后存量編碼沒遷移。解決思路是把編碼生成收斂到單一命名服務(wù)下游只做映射不做生成存量數(shù)據(jù)做一次編碼對齊和沖突清單人工確認后再合并。5.3 拓撲圖上出現(xiàn)指向不存在資源的連線現(xiàn)象拓撲視圖里一條鏈路的一端是空的點開報資源不存在。原因是資源退網(wǎng)時只刪了主表記錄關(guān)系表沒級聯(lián)清理或者關(guān)系表壓根沒有完整性約束。解決思路是退網(wǎng)走狀態(tài)標記關(guān)系表加兩端存在性校驗定期跑完整性巡檢把懸空關(guān)系掛出來修。5.4 同一批文件導(dǎo)入兩次產(chǎn)生重復(fù)資源現(xiàn)象批量導(dǎo)入重跑了一次資源列表里出現(xiàn)兩條同名同編碼的記錄。原因是沒有冪等鍵導(dǎo)入邏輯是純插入。解決思路是以業(yè)務(wù)編碼加資源類型做唯一約束導(dǎo)入改成 upsert重復(fù)行不報錯記進沖突報告讓人工確認。導(dǎo)入工具還要支持“試運行”先出差異清單再落庫。5.5 割接完成后系統(tǒng)里的路由和現(xiàn)網(wǎng)對不上現(xiàn)象割接施工完成了但資源系統(tǒng)里舊路由還在新路由沒生效下游查詢拿到的是過期數(shù)據(jù)。原因是割接流程沒閉環(huán)報竣環(huán)節(jié)只改了工單狀態(tài)沒觸發(fā)資源數(shù)據(jù)變更。解決思路是把資源報竣設(shè)為流程必經(jīng)節(jié)點報竣時統(tǒng)一寫資源變更和機歷割接前后各跑一次數(shù)據(jù)比對差異超過閾值就阻斷歸檔。6. 設(shè)計取舍模板化的靈活性和數(shù)據(jù)可信度怎么平衡資源管理系統(tǒng)做久了會發(fā)現(xiàn)所有設(shè)計最后都落在幾個取舍上。第一個取舍是模板化與查詢性能。元模型驅(qū)動讓新增資源類型變成插數(shù)據(jù)擴展性很好代價是查詢要拼擴展表或者解析文檔字段復(fù)雜統(tǒng)計會慢。常見的折中是分層高頻查詢的核心資源機房、設(shè)備、端口、電路用寬表冗余關(guān)鍵屬性長尾資源走擴展屬性寬表由模板變更觸發(fā)異步重建而不是每次寫入都同步刷。第二個取舍是強一致與最終一致。兩級三層部署下省級系統(tǒng)是資源數(shù)據(jù)的生產(chǎn)源頭總部做匯聚和跨省共享。要求強一致跨層同步的代價會高到不可接受所以通常是省級為準、總部準實時匯聚共享服務(wù)在返回結(jié)果里標注數(shù)據(jù)時效。下游如果拿資源數(shù)據(jù)做自動化開通必須能接受分鐘級延遲否則就要走實時查詢接口而不是訂閱。第三個取舍是全量共享與按需訂閱。共享服務(wù)如果全量推送下游壓力大、重復(fù)存儲多按需訂閱加變更通知更現(xiàn)實但要求上游能穩(wěn)定產(chǎn)出變更事件。事件丟失或亂序下游數(shù)據(jù)就會漂——這又回到機歷和變更序號的設(shè)計。驗證這套東西是否可信我會盯幾個指標資源編碼合規(guī)率按規(guī)則可解析的比例、拓撲完整性懸空關(guān)系占比、機歷覆蓋率關(guān)鍵變更是否有記錄、共享接口時延與變更通知到達率。抽樣比對也少不了從現(xiàn)網(wǎng)挑一百條資源和系統(tǒng)里的屬性、位置、連接關(guān)系逐項對比看報表管用。從那以后我每次接手資源類項目第一件事不是看功能清單而是先抽查一百條資源編碼和拓撲關(guān)系再拉一份最近的機歷看看變更有沒有斷檔。地基不牢功能寫得再花哨也是空中樓閣。希望幫到你。本文還有配套的精品資源點擊獲取