基於PostgreSQL實時干預搜尋排序實踐
1.引言
閒魚在產品的快速發展過程中,存在大量基於搜尋構建的feeds型場景,基於閒魚主搜尋通用演算法構建的排序有時候不能有效的滿足場景需求,出現無法體現場景特點的問題,需要進行精準的實時線上干預能力。本文介紹了一種基於阿里雲的HybridDB for PostgreSQL資料庫,構建搜尋排序實時干預能力的方案。
2.實時干預搜尋排序挑戰
搜尋不僅僅是依賴單一排序欄位,而是多種演算法進行打分,計算權重後得到的綜合得分進行排序,然而由於閒魚二手商品特性,其商品主要來自個人賣家的閒置商品,商品往往是孤品,同時商品的價值很難衡量,因此對實時性要求很嚴格,新發商品和商品變化,都需要觸發打分重算,進而影響排序,整個流程如下:
實現上圖流程的挑戰主要有幾個方面
實時性 秒級的實時干預能力
資料合併能力 高效合併任意資料來源資料
資料處理 支援億級的資料處理能力
3.實現方案
3.1 PostgreSQL 能力
PostgreSQL是一個歷史悠久的資料庫,最早由加州大學伯克利分校的Michael Stonebraker教授領導設計,具備與Oracle類似的功能、效能、架構以及穩定性。
阿里雲HybridDB for PostgreSQL,提供大規模並行處理(MPP)資料倉儲服務, 支援多核平行計算、向量計算、圖計算、JSON,JSONB全文檢索。
3.2 系統架構
PostgreSQL高效的並行處理能力,基於JSON格式資料合併能力以及Notify實時訊息能力,給我們提供了具體實現思路。因此基於上文提到業務挑戰,我們梳理了相關實現方案。
仔細分析整體方案,歸納起來涉及的方面有:
異構資料來源接入
歸一化服務
資料合併策略
實時分數重算
異構資料來源接入
閒魚商品相關的資料非常豐富,有各種異構資料來源,如全量的離線商品資料,實時商品變更資料,各種演算法維度資料等,在實現上可透過阿里雲大資料平臺,binlog監聽工具等進行統一處理。
如上圖所示,所有異構資料來源都按照統一格式,透過非同步訊息,輸入到歸一化服務,該方案的優點是不管全量資料還是增量資料都統一走訊息服務,簡化接入流程,同時透過訊息中間層進行解耦,提高穩定性。
歸一化服務
歸一化服務接收上游異構資料來源訊息,透過資料校驗模組、資料補全模組、標準格式轉換模組、資料監控模組為下游輸送正確的資料。
資料校驗模 如下圖所示,資料來源結合後設資料中心進行欄位級別的校驗,如欄位名稱,資料型別,資料範圍、預設值等,引入後設資料中心最大優勢是可以細粒度的控制資料來源,防止髒資料、不需要的資料汙染下游。
資料補全模組 資料來源通常需要實時補全一些資料干預指標,如使用者編輯商品,需實時分析打標是否有黃圖,商品價格預測等,整個干預流程要以pipeline的形式,暴露擴充套件點,允許插入干預能力。
標準格式轉換模組 標準格式轉換模組將資料來源統一按標準的格式轉換成JSON結構,便於下游統一資料合併。
資料監控模組 資料監控模組記錄資料來源的每一條資料以及異常資料記錄,並將資料投遞到監控系統,監控每個異構資料來源異常資料,流量異常情況,第一時間發現並恢復問題。
資料合併策略
資料合併策略主要包括基於時間戳的資料合開和資料變更通知兩個先後處理流程,在資料合併流程會遇到一個核心問題,即如何快速有效的解決每個欄位的衝突合併,基於時間戳統一merge。這裡首先會涉及到資料儲存結構,參考如下表設計結構:
create table Test (id int8 primary key, -- 商品IDatt jsonb -- 商品屬性);
屬性設計為JSON,JSON裡面是K-V的屬性對,如下屬性結構示例,V裡面是陣列,包含K的值以及這對屬性的最後更新時間,更新時間用於merge update,當屬性發生變化時才更新,沒有發生變化時,不更新。這種設計優點:
欄位級別細粒度merge,保證最小集資料實時性
高擴充套件性,表不需要增減欄位
屬性結構示例
{"count": [100, "2017-01-01 10:10:00"], "price": [8880, "2018-01-04 10:10:12"], "newatt": [120, "2017-01-01 12:22:00"]}
定義完儲存結構, 接下來利用PostgreSQL的JSON處理能力進行資料merge,參考如下merge udf 虛擬碼:
create or replace function merge_json(jsonb, jsonb) returns jsonb as $$ select jsonb_object_agg(key,value) from ( select coalesce(a.key, b.key) as key, case when coalesce(jsonb_array_element(a.value,1)::text::timestamp, '1970-01-01'::timestamp) > coalesce(jsonb_array_element(b.value,1)::text::timestamp, '1970-01-01'::timestamp) then a.value else b.value end from jsonb_each($1) a full outer join jsonb_each($2) b using (key) ) t; $$ language sql strict ;
定義完merge方法後,我們在資料來源有資料變更時直接呼叫。
insert into a values (1, '{"price":[1000, "2019-01-01 10:10:12"], "newatt": ["hello", "2018-01-01"]}') on conflict (id) do update set att = merge_json(a.att, excluded.att) where a.att <> merge_json(a.att, excluded.att);
從上面可以看出當商品ID出現衝突時,會呼叫merge_json 進行資料合併,至此資料合併流程完成,接下來需要將合併結果實時通知下游,可以利用PostgreSQL的觸發品和Notify機制來處理。
觸發器設計
//觸發器要執行的udf CREATE OR REPLACE FUNCTION notify1() returns trigger AS $function$ declare begin perform pg_notify( 'a', -- 非同步訊息通道名字 format('CLASS:notify, ID:%s, ATT:%s', NEW.id, NEW.att) -- 訊息內容 ); return null; end $function$ language plpgsql strict; //建立觸發器 create trigger tg1 after insert or update on Test for each row execute procedure notify1();
可以看出當資料插入或更新會觸發trigger 執行nofity1 函式建立非同步nofity訊息,並向指定的通道傳送通知,下游應用可透過jdbc監聽相應的通道,接收訊息,進行後續實時打分流程,參考如下虛擬碼:
this.pgconn = conn.unwrap(org.postgresql.PGConnection.class); Statement stmt = conn.createStatement(); stmt.execute("LISTEN a"); stmt.close(); org.postgresql.PGNotification notifications[] = pgconn.getNotifications(); if (notifications != null) { for (int i=0; i < notifications.length; i++) { System.out.println("Got notification: " + notifications[i].getName()); } }
另外PostgreSQL併發處理效能非常高效,繫結觸發器後會增加PostgreSQL的資料寫入時長,但是壓測結果來看,依然能夠滿足我們的業務寫入效能要求,
以1000萬資料測試結果為例:
資料實時打分干預搜尋
服務層在監聽到Notify訊息,解析訊息資料,透過規則引擎對各指標權重進行分數重算,計算綜合分數,打到搜尋tag表,搜尋引擎實時監測tag表,將綜合分數dump到搜尋引擎,實時干擾排序結果。
4.總結
本文主要介紹閒魚如何利用PostgreSQL提共的能力去構建實時干預搜尋排序,在資料流上透過異構資料來源的統一接入,歸一化服務的統一處理,PostgreSQL的資料合併和Notify通知機制,規則引擎分數重算,實時搜尋dump干預來實現實時鏈路打通。希望給各位讀者帶來一些思考和啟發。系統目前在閒魚免費送場景應用,達到秒級的實時干預能力,商品成交數提升30%,好評率持續提升 28%, 未來我們將會構建更豐富的應用場景,如果感興趣或者有更好的解決思路,歡迎和我們交流。
5.參考資料
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900359/viewspace-2222536/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 基於 Kafka 的實時數倉在搜尋的實踐應用Kafka
- 基於Kafka和Elasticsearch構建實時站內搜尋功能的實踐KafkaElasticsearch
- 大眾點評搜尋基於知識圖譜的深度學習排序實踐深度學習排序
- elasticsearch實現基於拼音搜尋Elasticsearch
- 基於Elasticsearch實現搜尋建議Elasticsearch
- 美團搜尋多業務商品排序探索與實踐排序
- 【搜尋引擎】 PostgreSQL 10 實時全文檢索和分詞、相似搜尋、模糊匹配實現類似Google搜尋自動提示SQL分詞Go
- jQuery 條件搜尋查詢 實時取值 升降序排序jQuery排序
- Apache Doris在京東搜尋實時OLAP中的應用實踐Apache
- 基於 Elasticsearch 的站內搜尋引擎實戰Elasticsearch
- 直播開發app,實時搜尋、搜尋引擎框APP
- 智慧搜尋模型預估框架Augur的建設與實踐模型框架
- 深度學習在美團搜尋廣告排序的應用實踐深度學習排序
- 端智慧在大眾點評搜尋重排序的應用實踐排序
- 基於Greenplum,postgreSQL的大型資料倉儲實踐SQL
- 前端實時搜尋框模擬前端
- 基於 Mysql 實現一個簡易版搜尋引擎MySql
- 搜尋引擎分散式系統思考實踐分散式
- 內容社群行業搜尋最佳實踐行業
- 基於 Flink 的實時數倉生產實踐
- 從KDD 2018最佳論文看Airbnb實時搜尋排序中的Embedding技巧AI排序
- PostgreSQL實踐-實時廣告位推薦2(任意欄位組合、任意維度組合搜尋、輸出TOP-K)SQL
- PostgreSQL家譜、族譜類應用實踐-圖式關係儲存與搜尋SQL
- 上海久耶基於HBase實時數倉探索實踐
- 錢大媽基於 Flink 的實時風控實踐
- 搜尋趨勢:微軟必應新版整合AI和實時搜尋微軟AI
- Nebula 基於 ElasticSearch 的全文搜尋引擎的文字搜尋Elasticsearch
- [計算機視覺]基於內容的影像搜尋實現計算機視覺
- python 手把手教你基於搜尋引擎實現文章查重Python
- Elasticsearch 近實時搜尋的底層原理Elasticsearch
- 網易雲音樂基於Flink實時數倉實踐
- 基於雲原生的大資料實時分析方案實踐大資料
- 快手基於 Apache Flink 的實時數倉建設實踐Apache
- 愛奇藝逗芽表情搜尋分析與實踐
- 騰訊音樂知識圖譜搜尋實踐
- 基於 SplPriorityQueue 實現的排序方法排序
- 快手基於 Flink 構建實時數倉場景化實踐
- 基於Azkaban的任務定時排程實踐