實時業(yè)務風控系統(tǒng)

項目地址

代碼已開源, https://github.com/sunpeak/riskcontrol

背景

當前互聯(lián)網(wǎng)企業(yè)存在很多業(yè)務風險,有些風險(比如薅羊毛)雖然沒有sql注入漏洞利用來的直接,但是一直被羊毛黨、刷單黨光顧的企業(yè)長期生存下來的幾率會很低!

  • 賬號:垃圾注冊、撞庫、盜號等

  • 交易:盜刷、惡意占用資源、篡改交易金額等

  • 活動:薅羊毛

  • 短信:短信轟炸

項目介紹

實時業(yè)務風控系統(tǒng)是分析風險事件,根據(jù)場景動態(tài)調(diào)整規(guī)則,實現(xiàn)自動精準預警風險的系統(tǒng)。

本項目只提供實時風控系統(tǒng)框架基礎(chǔ)和代碼模板。

需要解決的問題

  • 哪些是風險事件,注冊、登錄、交易、活動等事件,需要業(yè)務埋點配合提供實時數(shù)據(jù)接入

  • 什么樣的事件是有風險的,風險分析需要用到統(tǒng)計學,對異常用戶的歷史數(shù)據(jù)做統(tǒng)計分析,找出異于正常用戶的特征

  • 實時性,風險事件的分析必須毫秒級響應,有些場景下需要盡快攔截,能夠給用戶止損挽回損失

  • 低誤報,這需要人工風控經(jīng)驗,對各種場景風險閾值和評分的設置,需要長期不斷的調(diào)整,所以靈活的規(guī)則引擎是很重要的

  • 支持對歷史數(shù)據(jù)的回溯,能夠發(fā)現(xiàn)以前的風險,或許能夠找到一些特征供參考

項目標簽

  • 輕量級,可擴展,高性能的Java實時業(yè)務風控系統(tǒng)

  • 基于Spring boot構(gòu)建,配置文件能少則少

  • 使用drools規(guī)則引擎管理風控規(guī)則,原則上可以動態(tài)配置規(guī)則

  • 使用redis、mongodb做風控計算和事件儲存,歷史事件支持水平擴展

原理

統(tǒng)計學

  • 次數(shù)統(tǒng)計,比如1分鐘內(nèi)某賬號的登錄次數(shù),可以用來分析盜號等

  • 頻數(shù)統(tǒng)計,比如1小時內(nèi)某ip上出現(xiàn)的賬號,可以用來分析黃牛黨等

  • 最大統(tǒng)計,比如用戶交易金額比歷史交易都大,可能有風險

  • 最近統(tǒng)計,比如最近一次交易才過數(shù)秒,可能機器下單

  • 行為習慣,比如用戶常用登錄地址,用戶經(jīng)常登錄時間段,可以用來分析盜號等

通用公式:某時間段,在條件維度(可以是多個維度復合)下,利用統(tǒng)計方法統(tǒng)計結(jié)果維度的值,充分發(fā)揮你的想象吧!

實時計算

要將任意維度的歷史數(shù)據(jù)(可能半年或更久)實時統(tǒng)計出結(jié)果,需要將數(shù)據(jù)提前安裝特殊結(jié)果準備好(由于事件的維度數(shù)量不固定的,選取統(tǒng)計的維度也是隨意的,所以不是在關(guān)系數(shù)據(jù)庫中建幾個索引就能搞定的),需要利用空間換時間,來降低時間復雜度。

redis

redis中數(shù)據(jù)結(jié)構(gòu)sortedset,是個有序的集合,集合中只會出現(xiàn)最新的唯一的值。利用sortedset的天然優(yōu)勢,做頻數(shù)統(tǒng)計非常有利。

比如1小時內(nèi)某ip上出現(xiàn)的賬號數(shù)量統(tǒng)計:

  • 保存維度

    ZADD key score member(時間復雜度:O(M*log(N)), N 是有序集的基數(shù), M 為成功添加的新成員的數(shù)量),key=ip,score=時間(比如20160807121314),member=賬號。存儲時略耗性能。

結(jié)構(gòu)如下:

1.1.1.1

|--賬號1        20160807121314

|--賬號2        20160807121315

|--賬號n        20160807121316


2.2.2.2

|--賬號3        20160807121314

|--賬號4        20160807121315

|--賬號m        20160807121316
  • 計算頻數(shù)

    ZCOUNT key min max(時間復雜度:O(1)),key=ip,min=起始時間,max=截止時間。計算的性能消耗極少,優(yōu)勢明顯

  • redis lua

    把保存維度,計算頻數(shù),過期維度數(shù)據(jù)等操作,使用lua腳本結(jié)合在一起,可以減少網(wǎng)絡IO,提供性能

mongodb

mongodb本身的聚合函數(shù)統(tǒng)計維度,支持很多比如:max,min,sum,avg,first,last,標準差,采樣標準差,復雜的統(tǒng)計方法可以在基礎(chǔ)聚合函數(shù)上建立,比如行為習慣:

getDB().getCollection(collectionName).aggregate(

  Arrays.asList(

    match(match)                                                       --匹配條件維度

    , group("$" + field, Accumulators.sum("_count", 1))                --求值維度的次數(shù)

    , match(new Document("_count", new Document("$gte", minCount)))   --過濾,超過minCount才統(tǒng)計

    , sort(new Document("_count", -1))                                --對次數(shù)進行倒敘排列

  )

);

建議在mongodb聚合的維度上建立索引,這樣可以使用內(nèi)存計算,速度較快。

redis性能優(yōu)于mongodb,所以使用場景較多的頻數(shù)計算默認在redis中運行,參考代碼DimensionService.distinctCountWithRedis方法。但是redis為了性能犧牲了很多空間,數(shù)據(jù)重復存儲,會占用很多內(nèi)存。

環(huán)境準備

  • mysql,數(shù)據(jù)結(jié)構(gòu)在import.sql中定義了

  • redis

  • mongodb,建議使用分片集群

項目配置

  • 應用配置:application.properties

  • 日志配置:logback.xml

  • 規(guī)則配置:rules/*.drl,規(guī)則都是用java語言編寫。默認配置了登錄事件的部分規(guī)則

單個規(guī)則文件說明:

package rules;                                        --規(guī)則包路徑

import com.example.riskcontrol.model.LoginEvent        --引入類

import com.example.riskcontrol.service.DimensionService

import com.example.riskcontrol.model.EnumTimePeriod

global DimensionService dimensionService             --引入外部服務

rule "98_login_ip"                                   --規(guī)則名稱,全局唯一

  salience 98                                        --規(guī)則優(yōu)先級,值越大越先執(zhí)行

  lock-on-active true                                --事件不重復執(zhí)行該規(guī)則

when                                                 --條件判斷,是否需要進入action

  event:LoginEvent()                                --判斷事件對象是否是LoginEvent類

then                                                --action

  int count  = dimensionService.distinctCount(event,new String[]{LoginEvent.OPERATEIP},EnumTimePeriod.LASTHOUR,LoginEvent.MOBILE);        --近1小時內(nèi)該事件ip上出現(xiàn)的mobile數(shù)量統(tǒng)計

  if(event.addScore(count,20,10,1)){        --如果統(tǒng)計結(jié)果超過20個,則記10分,并且結(jié)果每超1個,再多記1分

    dimensionService.insertRiskEvent(event,"近1小時內(nèi)同ip出現(xiàn)多個mobile,count="+count);  --記錄風險事件日志

  }

end       --結(jié)束規(guī)則

drools的詳細文檔,請參考官方http://docs.jboss.org/drools/release/6.4.0.Final/drools-docs/html_single/index.html

部署

系統(tǒng)默認采用jar打包和運行,建議集群方式部署,然后使用反向代理做負載均衡。

打包

mvn clean install

運行

建議jdk 8

java -jar riskcontrol-*.jar

war包部署

如果需要tomcat等容器部署,也可將配置打包方式修改成war包方式,修改pom.xml

 <packaging>war</packaging>

風控分析入口

TODO

  • 擴展黑白名單,ip,手機號,設備指紋等;

  • 擴展維度信息,比如手機號地域運營商,ip地域運營商,ip出口類型,設備指紋,Referer,ua,密碼hash,征信等,維度越多,可以建立規(guī)則越多,風控越精準;

  • 擴展風控規(guī)則,針對需要解決的場景問題,添加特定規(guī)則,分值也應根據(jù)自身場景來調(diào)整。

  • 將用戶的行為軌跡綜合考慮,建立復合場景的規(guī)則條件。比如:登錄->活動->訂單->支付,將事件關(guān)聯(lián)分析綜合考慮;

  • 減少漏報和誤報。當然,這將是個漫長的過程;

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

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

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