2018剛過去,趁着春節放假對過去一年主導開發的項目作個梳理和總結html
平臺運營到必定階段,必定會累積大批量的用戶數據,這些用戶數據是運營人員的黃金財產。而如何利用用戶的數據來作運營(消息推送、觸達消息、優惠券發送、廣告位等),正是精準運營系統須要解決的問題。本文是基於信貸業務實踐後寫出來的,其它行業如保險、電商、航旅、遊戲等也能夠參考。前端
先看幾個具備表明性的需求mysql
用戶可用額度在20000~50000元,並且有借款記錄,未還本金爲0,性別爲「男」
用戶發生了A行爲且未還本金大於5000
用戶在1天內發生A行爲次數大於等於3次
用戶在A行爲前24小時內未發生B行爲
用戶在A行爲後一個月內未發生B行爲
業務上有兩種消息類型sql
對於用戶篩選條件,也主要有兩種類型數據庫
早期方案存在如下痛點apache
下面重點看下kafka connector和Elasticsearch如何使用json
kafka connector有Source和Sink兩種組件,Source的做用是讀取數據到kafka,這裏用開源實現debezium來採集mysql的binlog和postgres的xlog。Sink的做用是從kafka讀數據寫到目標系統,這裏本身研發一套組件,根據配置的規則將數據格式化再同步到ES。
kafka connector有如下優勢:api
對於狀態數據,因爲狀態的寫操做相對較少,咱們採起嵌套文檔的方式,將同個用戶的相關實體數據都同步寫入到同個文檔,具體實現用painless腳本作局部更新操做。效果相似這樣:性能優化
{ "id":123, "age":30, "credit_line":20000, "education":"bachelor", ... "last_loan_applications":{ "loan_id":1234, "status":"reject", ... } ... }
事件數據寫入比較頻繁,數據量比較多,咱們使用父子文檔的方式作關聯,效果相似這樣:微信
{ "e_uid":123, "e_name":"loan_application", "e_timestamp":"2019-01-01 10:10:00" ... }
(e_前綴是爲了防止同個index下同名字段衝突)
ES這樣存儲一方面是方便作統計報表,另外一方面跟用戶篩選和觸達有關。
在設計規則引擎前,咱們對業界已有的規則引擎,主要包括Esper, Drools, Flink CEP,進行了初步調研。
Esper設計目標爲CEP的輕量級解決方案,能夠方便的嵌入服務中,提供CEP功能。
優點:
劣勢:
Drools開始於規則引擎,後引入Drools Fusion模塊提供CEP的功能。
優點:
劣勢:
Flink 是一個流式系統,具備高吞吐低延遲的特色,Flink CEP是一套極具通用性、易於使用的實時流式事件處理方案。
優點:
劣勢:
綜上對比了幾大開源規則引擎,發現都沒法知足業務需求:
最終咱們選擇本身根據業務須要,開發基於json的自定義規則,規則相似下面例子:
{ "batchId": "xxxxxxxx", //流水號,建立每條運營規則時生成 "type": "trigger", //usual "triggerEvent": "login", "after": "2h", //分鐘m,小時h,天d,月M "pushRules": [//支持同時推送多條不一樣類型的消息 { "pushType": "sms", //wx,app,coupon "channel": "cl", "content": "hello #{userInfo.name}" }, { "pushType": "coupon", "couponId": 1234 } ], "statusConditions": [ { "name": "and", //邏輯條件,支持與(and)或(or)非(not) "conditions": [ { "name": "range", "field": "credit_line", "left": 2000, "right": 10000, "includeLeft": true, "includeRight": false }, { "name":"in", "filed":"education", "values":["bachelor","master"] } ] } ], "eventConditions": [ { "name": "or",//邏輯條件,支持與(and)或(or)非(not) "conditions": [ { "name": "event", "function": "count", //聚合函數,目前只支持count "eventName": "xxx_button_click", "range": { //聚合結果作判斷 "left": 1, "includeLeft": true }, "timeWindow": { "type": "fixed", //fixed爲固定窗口,sliding爲滑動窗口 "start": "2019-01-01 01:01:01", "end": "2019-02-01 01:01:01" }, "conditions": [ //event查詢條件繼承and邏輯條件,因此事件也能夠過濾字段 { "name": "equals", "field": "f1", "value": "v1" } ] } ] } ] }
使用面向對象思惟對過濾條件作抽象後,過濾條件繼承關係以下:
而後代碼里加一層parser把Condition都轉成ES查詢語句,實現輕量級的業務規則配置功能。
系統組成模塊及功能以下:
mysql binlog:mysql的數據變動,由kafka connector插件讀取到kafka,數據源之一
postgres xlog:pg的數據變動,由kafka connector插件讀取到kafka,數據源之一
report server:事件上報服務,數據源之一
tags:用戶畫像系統計算出來的標籤,數據源之一
觸發場景路由:分實時觸發和延遲觸發,實時觸發直接到下一步,延遲觸發基於 rabbitmq的延遲隊列實現
用戶篩選模塊:將篩選規則翻譯爲ES查詢語句到ES查詢用戶數據,能夠是批量的和單個用戶的
變量渲染模塊:對推送內容作處理
推送適配器:兼容不一樣的推送方式
定時任務調度器:基於elastic-job,處理定時推送任務
規則配置控制檯:提供可視化配置界面(運營規則配置、數據採集規則配置、字段元數據配置等)
報表服務:提供報表查詢功能
運營位服務:提供外部接口,根據條件匹配運營位(如啓動圖、首頁banner圖片等)
將來會繼續從技術及業務兩方面入手,將系統建設的更加易用、高效。