自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

常用性能優(yōu)化手段及在風(fēng)控系統(tǒng)中的應(yīng)用

開發(fā) 前端
性能優(yōu)化的手段有多種方式,本篇文章只是結(jié)合近期在風(fēng)控系統(tǒng)中的應(yīng)用實(shí)踐進(jìn)行的一個(gè)總結(jié),需要說明的是,其中有的優(yōu)化手段有利也有弊,得到的同時(shí)也在失去,可見,任何優(yōu)化手段都得以業(yè)務(wù)可接受為前提,因地制宜才是正道。

引言

性能優(yōu)化是個(gè)恒久的話題,隨著產(chǎn)品的演進(jìn),業(yè)務(wù)的增長(zhǎng),系統(tǒng)能力總有達(dá)到瓶頸的一天,它不可或缺的陪伴著我們走向壯大再走向衰敗,是我們面臨的不可回避的問題。下圖1展示了風(fēng)控系統(tǒng)近半年來承載流量的增長(zhǎng)趨勢(shì),可見最近半年來流量高速增長(zhǎng),且對(duì)于可預(yù)見的未來而言,接入流量還會(huì)持續(xù)高增。伴隨著流量的增長(zhǎng),系統(tǒng)各方面--存儲(chǔ)、計(jì)算、IO等都表現(xiàn)出一定的瓶頸,通過原始簡(jiǎn)單的水平擴(kuò)容并不能解決所有的問題,而且還會(huì)帶來成本的上升。因此,我們近期對(duì)系統(tǒng)進(jìn)行了一系列優(yōu)化改造, 目的是滿足未來一段時(shí)間內(nèi)業(yè)務(wù)的增長(zhǎng)使用,降低接口的耗時(shí)滿足某些延時(shí)敏感型業(yè)務(wù)的需要,同時(shí)也伴隨著一定的IT成本優(yōu)化。本文結(jié)合常見的性能優(yōu)化手段(預(yù)取、批量、異步、壓縮、緩存),及在風(fēng)控系統(tǒng)中的實(shí)踐進(jìn)行總結(jié),希望能給讀者對(duì)于性能優(yōu)化實(shí)踐帶來一些參考。

圖1:風(fēng)控引擎流量增長(zhǎng)趨勢(shì)圖1:風(fēng)控引擎流量增長(zhǎng)趨勢(shì)

預(yù)取——特征預(yù)計(jì)算

預(yù)取作為一種提速手段,通常與緩存搭配使用,在緩存空間換時(shí)間的基礎(chǔ)上更進(jìn)一步,以時(shí)間換時(shí)間,通過預(yù)加載來提升性能。常見的使用有,數(shù)據(jù)庫(kù)從磁盤加載頁時(shí)的預(yù)讀多個(gè)頁減少磁盤IO、CPU緩存加載一片連續(xù)的內(nèi)存空間提高計(jì)算的速度,也就是我們常說的CPU對(duì)數(shù)組友好對(duì)鏈表不友好的原因。

在Gaia風(fēng)控引擎中,一次業(yè)務(wù)請(qǐng)求在引擎內(nèi)部的執(zhí)行流程如下圖2所示,會(huì)經(jīng)歷場(chǎng)景因子(特征)->規(guī)則->決策的計(jì)算過程, 而計(jì)算因子是整個(gè)鏈路最耗時(shí)的部分,通常占請(qǐng)求響應(yīng)時(shí)間的70%以上,包括對(duì)賬號(hào)信息、名單庫(kù)、模型數(shù)據(jù)、用戶畫像、設(shè)備指紋、三方特征等多個(gè)下游的讀擴(kuò)散–特征因子獲取,加上場(chǎng)景的上百條規(guī)則執(zhí)行,請(qǐng)求耗時(shí)常規(guī)在250ms左右,這也是22年中以前我們承諾給主站大部分業(yè)務(wù)的響應(yīng)時(shí)間,直到電商業(yè)務(wù)的接入,對(duì)我們引擎的響應(yīng)時(shí)間提出了100ms以內(nèi)響應(yīng)的要求,迫使我們對(duì)引擎進(jìn)行了一些優(yōu)化,其中之一就是近線引擎帶來的特征預(yù)取優(yōu)化,其演進(jìn)流程如下圖3示:

圖2:風(fēng)控引擎一次請(qǐng)求執(zhí)行過程圖2:風(fēng)控引擎一次請(qǐng)求執(zhí)行過程

圖3:風(fēng)控特征獲取流程圖3:風(fēng)控特征獲取流程

基于一個(gè)前提:對(duì)同一個(gè)主體,按照其行為時(shí)序數(shù)據(jù)消費(fèi),slb數(shù)據(jù)源消費(fèi)處理完成大多數(shù)時(shí)候都要比業(yè)務(wù)請(qǐng)求風(fēng)控早。因此,我們通過對(duì)slb實(shí)時(shí)流數(shù)據(jù)消費(fèi)預(yù)讀取下游特征,并將結(jié)果緩存在redis中,當(dāng)業(yè)務(wù)請(qǐng)求風(fēng)控時(shí),直接獲取redis的數(shù)據(jù),避免或減少rpc回源特征,以此來降低風(fēng)控接口的耗時(shí)。

通過這套機(jī)制,我們按照特征變動(dòng)頻率對(duì)特征分層設(shè)置不同的緩存時(shí)間,同時(shí)在一些對(duì)數(shù)據(jù)一致性要求較低的場(chǎng)景對(duì)特征開啟緩存讀,其緩存命中率能達(dá)到90%以上,核心業(yè)務(wù)場(chǎng)景如電商交易,接口響應(yīng)耗時(shí)從80ms下降到25ms。

圖4:特征緩存命中率圖4:特征緩存命中率

圖5:電商交易場(chǎng)景請(qǐng)求風(fēng)控接口TP99耗時(shí)曲線圖圖5:電商交易場(chǎng)景請(qǐng)求風(fēng)控接口TP99耗時(shí)曲線圖


批量——特征批量獲取

批量一般是對(duì)I/O操作的優(yōu)化,同樣可看作是時(shí)間換時(shí)間,通過合并、批量進(jìn)行讀取或?qū)懭胍詼p少對(duì)I/O的操作來提升吞吐和性能。常見的使用有,kafka消費(fèi)數(shù)據(jù)的時(shí)候批量拉取指定的數(shù)據(jù)條數(shù),mysql寫入redolog/binlog時(shí)的組提交(group commit)機(jī)制,都是通過批量的優(yōu)化來減少I/O提升性能的。

在Gaia引擎中最常用的特征為對(duì)賬號(hào)管控/風(fēng)控名單值的獲取,一次業(yè)務(wù)風(fēng)險(xiǎn)判斷請(qǐng)求會(huì)涉及到對(duì)請(qǐng)求主體(mid、buvid、ip、ua)的各種黑/白名單值獲取,以主體mid為例,往往會(huì)并發(fā)調(diào)用下游名單接口多次,判斷mid是否在同設(shè)備多賬號(hào)黑名單、虛假賬號(hào)黑名單、通用白名單等名單中,從而形成不同的因子供規(guī)則使用,這種方式就會(huì)造成對(duì)同下游的同接口的讀擴(kuò)散流量放大浪費(fèi)資源,且要保持下游接口低延遲往往需要下游進(jìn)行擴(kuò)容保證CPU等資源使用率在一定的水位以下。因此,為了降低自身及下游的服務(wù)資源和I/O,優(yōu)化的手段就是將多次請(qǐng)求合并為一次請(qǐng)求,其優(yōu)化流程如下圖6所示:

圖6:名單類因子讀取優(yōu)化流程圖6:名單類因子讀取優(yōu)化流程

通過將多次獨(dú)立下游請(qǐng)求獲取給定黑/白名單轉(zhuǎn)化為一次批量請(qǐng)求獲取主體所有有效名單,同時(shí)結(jié)合本地內(nèi)存判斷因子請(qǐng)求名單與所有名單是否有交集來實(shí)現(xiàn)原有相同的功能,并通過local cache及singleflight優(yōu)化,降低對(duì)下游接口調(diào)用量69%。

圖7:實(shí)驗(yàn)環(huán)境名單庫(kù)接口批量?jī)?yōu)化效果圖7:實(shí)驗(yàn)環(huán)境名單庫(kù)接口批量?jī)?yōu)化效果

異步——累積因子同步改異步計(jì)算優(yōu)化

異步通常和同步一起對(duì)比,其區(qū)別在于發(fā)起請(qǐng)求之后是立即返回還是等待結(jié)果,常用于在系統(tǒng)內(nèi)部有大量I/O操作時(shí),通過異步提升吞吐。常見的使用有,基于write-back模式向緩存寫入數(shù)據(jù),mysql異步傳輸binlog進(jìn)行主從復(fù)制等。

在Gaia引擎中,一次請(qǐng)求會(huì)涉及對(duì)很多特征因子的計(jì)算,其中,最常用的是基于redis實(shí)現(xiàn)的累積因子,其包含如下幾種類型(見表1),以count(distinct)類型為例,一次計(jì)算過程包含1寫zadd,1讀zcount,概率觸發(fā)zrem清除不在有效時(shí)間窗口內(nèi)的過期數(shù)據(jù),其最多對(duì)redis請(qǐng)求3次,最少/均攤2次,且zset這幾個(gè)操作的時(shí)間復(fù)雜度都在O(log n)以上,加上一次請(qǐng)求往往會(huì)對(duì)多個(gè)累積因子進(jìn)行計(jì)算(讀寫擴(kuò)散),這給redis集群帶來了較大的計(jì)算壓力,由于overload對(duì)集群實(shí)例擴(kuò)容的限制,我們對(duì)redis集群的水平擴(kuò)容也遇到了瓶頸??紤]當(dāng)前引擎流量的情況:爬蟲類業(yè)務(wù)與常規(guī)業(yè)務(wù)流量占比為1.5:1,且爬蟲類業(yè)務(wù)流量還在持續(xù)高漲,鑒于爬蟲類業(yè)務(wù)風(fēng)控的特性(非資產(chǎn)安全,容忍一定的漏過),我們以犧牲數(shù)據(jù)一致性為代價(jià),對(duì)爬蟲類業(yè)務(wù)的累積因子進(jìn)行了異步計(jì)算優(yōu)化,以減少對(duì)redis的調(diào)用,其計(jì)算演進(jìn)流程如下圖8所示:

類型

功能

底層實(shí)現(xiàn)

使用頻率

count

計(jì)數(shù)

incr

count(distinct)

去重計(jì)數(shù)

zset

sum

累積求和

incrby

avg

累積求平均

incrby

表1:風(fēng)控引擎支持累積因子類型

圖8:累積因子計(jì)算(優(yōu)化前/后)流程圖8:累積因子計(jì)算(優(yōu)化前/后)流程

基于railgun(關(guān)于B站自研異步事件處理平臺(tái),可參閱:從1到億,如何玩好異步消息?CQRS架構(gòu)下的異步事件治理實(shí)踐)提供的內(nèi)存隊(duì)列聚合功能,我們對(duì)累積因子寫操作進(jìn)行了異步化改造,并結(jié)合聚合功能,在設(shè)置的時(shí)間/數(shù)量閾值條件下,對(duì)相同累積key進(jìn)行聚合并在內(nèi)存中去重后批量寫入redis,將多次同步redis I/O減少為異步寫1次。而優(yōu)化的效果從三個(gè)角度評(píng)估,從成本角度看:其對(duì)redis的調(diào)用qps減少了35%以上(如圖9);從接口耗時(shí)看:TP99有一定的下降; 從對(duì)風(fēng)控規(guī)則的召回影響看,前后召回趨勢(shì)基本一致,且打擊總量差距不大,在可接受的范圍內(nèi)。

圖9:?jiǎn)螆?chǎng)景累積因子計(jì)算優(yōu)化前/后對(duì)redis的調(diào)用量情況圖9:?jiǎn)螆?chǎng)景累積因子計(jì)算優(yōu)化前/后對(duì)redis的調(diào)用量情況

圖10:累積因子計(jì)算優(yōu)化前/后接口耗時(shí)情況圖10:累積因子計(jì)算優(yōu)化前/后接口耗時(shí)情況

圖11:累積因子計(jì)算優(yōu)化前/后規(guī)則召回的情況圖11:累積因子計(jì)算優(yōu)化前/后規(guī)則召回的情況

壓縮——日志存儲(chǔ)優(yōu)化

壓縮是常見的用于數(shù)據(jù)傳輸、持久化等過程中減少帶寬、存儲(chǔ)占用的方法,本質(zhì)是通過編碼的方式提高數(shù)據(jù)密度,減少數(shù)據(jù)的冗余度,一般以數(shù)據(jù)壓縮速度和壓縮率兩個(gè)指標(biāo)來衡量壓縮過程的效能。常用的無損壓縮方式有:gzip、xz、lz4、zlib、zstd等。

對(duì)于風(fēng)控業(yè)務(wù)來說,每一次風(fēng)控請(qǐng)求會(huì)產(chǎn)生包含輸入?yún)?shù)、計(jì)算詳情(計(jì)算規(guī)則、特征因子等中間結(jié)果的快照)、打擊決策等多個(gè)維度的日志數(shù)據(jù)。我們需要提供準(zhǔn)實(shí)時(shí)的查詢能力,用于輔助人工判定風(fēng)控決策的召回和誤傷等情況。由于一次風(fēng)控分析可能經(jīng)歷了上百條規(guī)則、上千個(gè)特征的計(jì)算,單條日志數(shù)據(jù)的平均大小達(dá)到了11KB左右,最大的高達(dá)幾十KB。基于風(fēng)控日志的特點(diǎn),我們把常用特征值(mid、buvid、ip等)和日志主體精簡(jiǎn)出來,使用ES存儲(chǔ)并提供關(guān)鍵字查詢。其他詳情(參數(shù)、中間結(jié)果等)則依托于B站自研的KV存儲(chǔ)taishan KV,以請(qǐng)求traceId為key進(jìn)行g(shù)zip壓縮后存儲(chǔ)。查詢時(shí)先基于ES查詢?nèi)罩局黧w,再對(duì)分頁記錄點(diǎn)查日志詳情并合并展示,其流程如圖12所示。這些優(yōu)化幫助風(fēng)控度過了22年之前接入場(chǎng)景大量增長(zhǎng)的階段,但隨著持續(xù)接入反爬蟲等大流量讀場(chǎng)景與降本增效帶來的雙重壓力下,風(fēng)控日志存儲(chǔ)陷入了瓶頸。

圖12:舊風(fēng)控日志詳情存儲(chǔ)與查詢過程圖12:舊風(fēng)控日志詳情存儲(chǔ)與查詢過程

以taishan KV存儲(chǔ)的日志詳情為例,總存儲(chǔ)達(dá)到了16TB左右。因此,我們期望能夠利用壓縮率更高的編碼方式和壓縮算法替代json+gzip的組合,進(jìn)一步優(yōu)化日志存儲(chǔ)。通過調(diào)研常見壓縮算法,結(jié)合日志詳情無壓縮速度要求的特點(diǎn),我們采集了線上真實(shí)日志作為實(shí)驗(yàn)集,選取了protobuf、msgpack等編碼方式和xz、zstd兩種算法進(jìn)行了多次對(duì)比實(shí)驗(yàn)。

在第一輪實(shí)驗(yàn)中,我們對(duì)比了單條日志在不同編碼方式下不同壓縮算法的壓縮率。實(shí)驗(yàn)隨機(jī)取同一場(chǎng)景下任意一條日志詳情進(jìn)行編碼和壓縮,重復(fù)多次后取各階段數(shù)據(jù)長(zhǎng)度平均值。其中,由于風(fēng)控日志包含了許多嵌套和非固定結(jié)構(gòu),難以使用protobuf等需要預(yù)定義結(jié)構(gòu)的序列化方式。因此我們嘗試了另一種高效的通用序列化框架msgpack。結(jié)果如表2所示。從結(jié)果上看,msgpack雖然編碼后比json更簡(jiǎn)短,但由于產(chǎn)生了許多非文本結(jié)構(gòu),最終壓縮率不及json。xz算法由于壓縮率無明顯優(yōu)勢(shì)且內(nèi)存占用較大而被棄用(圖13)。無字典模式下的zstd壓縮率略弱于gzip。

編碼方式

消息長(zhǎng)度

gzip

xz

zstd(無字典)

json

2255

1028

1092

1075

msgpack

1938

1088

1132

1119

表2:風(fēng)控日志在不同編碼方式、壓縮算法下的壓縮效果(單位:字節(jié))

圖13:各壓縮算法壓縮風(fēng)控日志的內(nèi)存占用圖13:各壓縮算法壓縮風(fēng)控日志的內(nèi)存占用

在第二輪實(shí)驗(yàn)中,我們使用json編碼方式,對(duì)比了gzip和zstd有無字典兩種模式下的壓縮率。其中,字典1由1萬條UAT爬蟲場(chǎng)景日志訓(xùn)練獲得,與線上日志差異較大。字典2由10000條線上爬蟲場(chǎng)景日志訓(xùn)練。首先是單條日志壓縮時(shí)不同zstd字典的影響,如表3所示。結(jié)果上,不使用字典時(shí)壓縮率最差,使用不匹配的字典略有提升。而使用匹配的字典后,zstd的壓縮率有顯著的提高。然后是對(duì)爬蟲場(chǎng)景不同數(shù)量的日志進(jìn)行批量壓縮對(duì)壓縮率的影響,如表4所示。zstd在小日志壓縮上使用匹配的字典壓縮效率較好,隨著每批次數(shù)量增多,壓縮率會(huì)相對(duì)降低,最終與gzip相當(dāng)。批量壓縮能夠顯著提高兩種算法的總體壓縮率,但單次超過10條以后遇到了邊際效應(yīng),收益急速降低。此外,我們基于任意單條日志進(jìn)行了多輪性能測(cè)試,表5展示了其中5輪測(cè)試結(jié)果。從壓縮性能角度分析,無論是否使用字典,zstd壓縮的效率都遠(yuǎn)超過gzip。

日志來源場(chǎng)景

消息長(zhǎng)度

gzip

zstd

(無字典)

zstd

(字典1)

zstd

(字典2)

說明

裂變拉新分享

25277

3869

4564

4236

4412

非同場(chǎng)景字典

爬蟲

4283

1434

1503

996

438

同場(chǎng)景字典

表3:風(fēng)控日志詳情在zstd算法下使用不同字典的壓縮效果

(單位:字節(jié))

每批

日志數(shù)

總計(jì)

日志數(shù)

gzip

zstd

(無字典)

zstd

(字典1)

zstd

(字典2)

1

100

154370

(1.000)

160582

(1.040)


111708

(0.723)


59195

(0.383)


10

100

58984

(1.000)


67036

(1.137)


59942

(1.016) 


47684

(0.808)


20

100

56085

(1.000)


63103

(1.125)


58509

(1.043)


56085

(1.000)


50

100

49152

(1.000)


55107

(1.121)


52927

(1.077)


48891

(0.995)


100

100

52439

(1.000)


56926

(1.086)


56076

(1.069)


53624

(1.023) 


1

1000

1607512

(1.000)


1668363

(1.038)


1154260

(0.718)


629463

(0.392)


100

1000

536579

(1.000) 


580076

(1.081)


572053

(1.066)


547021

(1.019) 


500

1000

546506

(1.000)


570690

(1.044)


571252

(1.045)


565319

(1.034) 


表4:不同數(shù)量的日志壓縮后數(shù)據(jù)大小總和與壓縮率對(duì)比(單位:字節(jié))

測(cè)試序號(hào)

gzip

zstd

(無字典)

zstd

(字典1)

zstd

(字典2)

1

123142

27509

31425

24474

2

139387

28246

31014

22763

3

148184

37118

37409

60840

4

158618

25168

29369

26504

5

170312

33782

47756

28951

表5:風(fēng)控日志在gzip與zstd算法壓縮性能對(duì)比(單位:ns/op)

綜合以上實(shí)驗(yàn),雖然zstd算法在壓縮效率上遠(yuǎn)優(yōu)于gzip,但僅在使用匹配的字典集時(shí),對(duì)單條日志的壓縮率遠(yuǎn)優(yōu)于gzip。另外,無論哪種壓縮算法都在批量壓縮中收益明顯,最高能夠減少60%的存儲(chǔ)。最后,由于我們對(duì)壓縮效率的需求較低,且訓(xùn)練zstd字典等改造成本較大等原因,我們選擇對(duì)現(xiàn)有的風(fēng)控日志詳情進(jìn)行批量壓縮改造(圖14)。實(shí)現(xiàn)上,基于railgun提供的聚合隊(duì)列功能,我們將消費(fèi)的日志分成n條若干批次,分配一個(gè)批處理ID(BatchId)并存儲(chǔ)到日志主體中,日志以BatchId為key批量gzip壓縮后存入taishan KV。查詢時(shí),獲取分頁下待查的BatchId,去重后批量從taishan KV拉取數(shù)據(jù),解壓后合并到日志中。對(duì)于查詢效率,最差情況下,每個(gè)BatchId都沒有去重,即每條數(shù)據(jù)多查詢了n-1條,請(qǐng)求數(shù)量不變,數(shù)據(jù)量變大N倍。實(shí)際查詢中,由于大多數(shù)查詢結(jié)果都是同一時(shí)段的連續(xù)數(shù)據(jù)集,因此實(shí)際去重效果較好,查詢效率略有提升。從存儲(chǔ)優(yōu)化上看,taishan KV寫入QPS由8k下降至1k左右,每秒寫入量由78MB下降為55MB,降幅約30%。表存儲(chǔ)TTL為7天,7日存儲(chǔ)下降約6TB,降幅約38%。

圖14:風(fēng)控日志詳情批量存儲(chǔ)與查詢過程圖14:風(fēng)控日志詳情批量存儲(chǔ)與查詢過程

緩存——多級(jí)緩存+布隆過濾器

緩存是最常見的加速數(shù)據(jù)交換的技術(shù),通?;趦?nèi)存等高速存儲(chǔ)器實(shí)現(xiàn),其本質(zhì)就是用空間換時(shí)間,犧牲一定的數(shù)據(jù)實(shí)時(shí)性,以減少各類IO的頻率,提升整體響應(yīng)速度。常見的緩存方案包括Cache Aside、Read/Write Through、Write-back等,適用于不同的業(yè)務(wù)場(chǎng)景。

在Gaia引擎中,名單庫(kù)服務(wù)是風(fēng)險(xiǎn)特征判斷的重要組成部分,采用了最常用的Cache Aside模式。名單庫(kù)服務(wù)的需求是一種經(jīng)典的讀多寫少場(chǎng)景:引擎將分屬不同名單的風(fēng)險(xiǎn)主體持久化存儲(chǔ)(100QPS以下),同時(shí)提供接口查詢指定主體是否屬于某一名單(上萬QPS)。因此,初期的名單庫(kù)采用了localCache+Redis Cache+MySQL存儲(chǔ)的模式實(shí)現(xiàn)查詢過程:寫入時(shí)刪除緩存,查詢時(shí)依次查詢Cache,直到回源DB查詢,并將實(shí)際值或空值寫入Cache。這一模式在低流量條件下表現(xiàn)優(yōu)異,直到風(fēng)控接入流量急速增長(zhǎng)至十萬以上時(shí),出現(xiàn)了越來越多的瓶頸問題,如:Redis CPU負(fù)載高、內(nèi)存占用高、DB回源超時(shí)等,DB存儲(chǔ)的名單個(gè)體數(shù)目也超過了3千萬并且持續(xù)快速增長(zhǎng)。這迫使我們做了許多優(yōu)化來滿足后續(xù)潛在的百萬級(jí)QPS查詢需求。其中最有效的就是布隆過濾器(Bloom Filter,BF)多級(jí)緩存優(yōu)化,具體的優(yōu)化過程如圖15所示。對(duì)于寫過程來說,新增更新服務(wù)訂閱了名單表的binlog,提供BF的全量/增量更新。對(duì)于讀過程來說,在原有多級(jí)緩存前新增BF Cache查詢,在確認(rèn)特征不存在的情況下直接返回結(jié)果。

圖15:名單庫(kù)服務(wù)BF多級(jí)緩存優(yōu)化過程——新老流程對(duì)比圖15:名單庫(kù)服務(wù)BF多級(jí)緩存優(yōu)化過程——新老流程對(duì)比

由于名單庫(kù)查詢時(shí),大多數(shù)用戶并無風(fēng)險(xiǎn),名單庫(kù)查詢存在普遍的緩存穿透問題。因此名單庫(kù)查詢天然配適BF的使用場(chǎng)景,但要實(shí)際落地,仍然面臨著許多問題:

  1. HotKey和BigKey問題。由于全集記錄超過3千萬條,單個(gè)BF容量越大,value越大,越容易出現(xiàn)集中訪問同一個(gè)key的熱點(diǎn)問題。因此需要對(duì)BF進(jìn)行合理的拆分。
  2. 維護(hù)問題。BF需要維護(hù)一個(gè)全集數(shù)據(jù),因此無論是本地還是分布式實(shí)現(xiàn),都需要具備基于全量數(shù)據(jù)構(gòu)建的能力。從數(shù)據(jù)安全性角度出發(fā),BF存在人為操作等導(dǎo)致非預(yù)期異常的可能,BF需要具備備份和快速恢復(fù)能力。
  3. 數(shù)據(jù)一致性問題。一方面,由于BF能夠確定的表述一個(gè)key不存在于全集中,因此需要保證DB與BF的最終一致性。為了保證新記錄一定存入BF,插入BF需要支持無限重試。另一方面,由于BF存在假陽率,且不能刪除個(gè)體,隨著名單過期、key數(shù)量逼近BF容量等情況的發(fā)生,BF實(shí)際假陽率會(huì)逐級(jí)升高導(dǎo)致過濾效果變差。因此需要支持BF容量擴(kuò)充和實(shí)現(xiàn)定期重建的能力。

由于Redis布隆過濾器插件完整的支持了BF的操作和自動(dòng)擴(kuò)容,我們選擇使用Redis作為BF的分布式實(shí)現(xiàn)。對(duì)于HotKey和BigKey問題,我們對(duì)BF進(jìn)行了隨機(jī)分片。為了保證BF Key分布均勻,人為的將分片總數(shù)BF_SLICE_SIZE定義為4倍Redis Slot數(shù)量,即65536個(gè)。每一個(gè)分片Key的命名格式為"{libKey_bf_" + sliceIndex + "}",其中sliceIndex為分片序號(hào),使用花括號(hào)來保證相同前綴的BF利用rename命令迭代替換時(shí)處于同一個(gè)Slot中。名單個(gè)體將按照sliceIndex = HashKey % BF_SLICE_SIZE計(jì)算自己所屬的分片,其中HashKey的取值為名單個(gè)體值的IEEE CRC32絕對(duì)值。此外,我們對(duì)BF設(shè)置了獨(dú)立的本地緩存以減少實(shí)際調(diào)用。由于BF只增不減的特點(diǎn),對(duì)于陽性結(jié)果,我們?cè)O(shè)置了較長(zhǎng)TTL。而對(duì)于陰性結(jié)果,則按業(yè)務(wù)容忍度設(shè)置了秒級(jí)TTL,保證及時(shí)獲取新插入個(gè)體。

對(duì)于維護(hù)問題,我們實(shí)現(xiàn)了完整的構(gòu)建工具。同時(shí),基于安全性考慮實(shí)現(xiàn)了備份和快速恢復(fù)流程?;跔顟B(tài)機(jī),我們定義了BF的構(gòu)建過程:初始化、異步構(gòu)建、同步測(cè)試、BF更新等。整個(gè)構(gòu)建過程使用分布式鎖保證唯一性,基于railgun定時(shí)任務(wù)周期性觸發(fā),整個(gè)過程記錄構(gòu)建進(jìn)度并提供實(shí)時(shí)展示和查詢。全過程如圖16所示。初始化時(shí),會(huì)Dump生成正在運(yùn)行的BF備份文件并存儲(chǔ)到對(duì)象存儲(chǔ)。生成新的BF臨時(shí)分片,以"_temp"尾綴區(qū)分。更新服務(wù)基于狀態(tài)變化將增量個(gè)體雙寫到臨時(shí)BF中。異步構(gòu)建過程會(huì)分批獲取完整的名單表,批量寫入存量個(gè)體到臨時(shí)BF中。之后進(jìn)行同步測(cè)試,利用少量增量和存量個(gè)體模擬查詢臨時(shí)BF,當(dāng)所有測(cè)試個(gè)體都存在于BF時(shí)通過測(cè)試。最后,將臨時(shí)BF原子性地替換正式BF,完成構(gòu)建過程??焖倩謴?fù)過程基于構(gòu)建的整體流程,部分模塊略有差異:初始化階段會(huì)獲取備份文件并嘗試restore數(shù)據(jù)到臨時(shí)BF中。異步構(gòu)建時(shí)則基于備份時(shí)間點(diǎn)開始獲取存量數(shù)據(jù)。

圖16:BF構(gòu)建與快速恢復(fù)流程圖16:BF構(gòu)建與快速恢復(fù)流程

對(duì)于數(shù)據(jù)一致性問題,我們提供了完整的控制、評(píng)估和測(cè)試BF一致性的流程。為了保證數(shù)據(jù)安全,我們定義了BF測(cè)試模式和正常模式兩種運(yùn)行方式,并可以按比例配置運(yùn)行,如圖17所示。測(cè)試模式下,查詢的BF值不會(huì)生效,流量進(jìn)入緩存查詢流程。之后基于查詢實(shí)際值對(duì)比結(jié)果進(jìn)行監(jiān)控報(bào)點(diǎn)并建立真陰性比例四個(gè)9等監(jiān)控告警。處于正常模式則會(huì)對(duì)BF假陽等情況進(jìn)行報(bào)點(diǎn)等。實(shí)際上線后,服務(wù)長(zhǎng)期保持一定比例的流量(當(dāng)前為0.1%)運(yùn)行測(cè)試模式,用于持續(xù)評(píng)估線上BF運(yùn)行狀態(tài)。圖18展示了BF查詢結(jié)果占比,約95%的查詢?yōu)殛幮?,?yōu)化收益明顯,如表6所示。在后續(xù)壓測(cè)中,名單庫(kù)服務(wù)具備了支撐百萬級(jí)流量的能力。

圖17:名單庫(kù)服務(wù)BF多級(jí)緩存優(yōu)化過程圖17:名單庫(kù)服務(wù)BF多級(jí)緩存優(yōu)化過程

圖18:名單庫(kù)服務(wù)線上流量BF查詢結(jié)果占比圖18:名單庫(kù)服務(wù)線上流量BF查詢結(jié)果占比

優(yōu)化項(xiàng)目

優(yōu)化前

優(yōu)化后

降幅

說明

服務(wù)CPU使用率

50.5%

17.5%

65%

日峰值同比

Redis 內(nèi)存占用

256GB

50GB

80%

日峰值同比

Redis 網(wǎng)絡(luò)IO

174/187Mbps

13.7/6.7Mbps

92%/96%

日峰值同比

Redis CPU使用率

42%

4%

90%

日峰值同比

BF Redis 內(nèi)存占用

0

7GB

-

新增10個(gè)節(jié)點(diǎn)

BF Redis 網(wǎng)絡(luò)IO

0

71.4/7.5Mbps

-

新增10個(gè)節(jié)點(diǎn)

BF Redis CPU使用率

0

10%

-

新增10個(gè)節(jié)點(diǎn)

MySQL 讀QPS

12k

600

95%

日峰值同比

表6:名單庫(kù)BF多級(jí)緩存優(yōu)化收益對(duì)比

總結(jié)

性能優(yōu)化的手段有多種方式,本篇文章只是結(jié)合近期在風(fēng)控系統(tǒng)中的應(yīng)用實(shí)踐進(jìn)行的一個(gè)總結(jié),需要說明的是,其中有的優(yōu)化手段有利也有弊,得到的同時(shí)也在失去,可見,任何優(yōu)化手段都得以業(yè)務(wù)可接受為前提,因地制宜才是正道。正如Linux性能優(yōu)化大師Brendan Gregg一再?gòu)?qiáng)調(diào)的:切忌過早優(yōu)化、過度優(yōu)化。

責(zé)任編輯:武曉燕 來源: 嗶哩嗶哩技術(shù)
相關(guān)推薦

2023-05-29 08:04:08

2022-06-14 16:38:42

行為序列機(jī)器學(xué)習(xí)黑產(chǎn)

2022-08-12 15:02:31

應(yīng)用探索

2024-07-15 08:59:52

機(jī)器學(xué)習(xí)弱監(jiān)督建模人工智能

2023-09-04 07:03:35

2023-02-15 21:49:55

2022-07-13 16:42:35

黑產(chǎn)反作弊風(fēng)險(xiǎn)

2017-02-24 19:45:58

2022-04-28 12:51:11

風(fēng)控中臺(tái)智能

2021-03-22 11:49:19

架構(gòu)運(yùn)維技術(shù)

2022-01-17 14:58:29

多云攻擊系統(tǒng)ID

2021-12-02 15:17:42

大數(shù)據(jù)銀行應(yīng)用

2010-11-15 16:20:33

Oracle系統(tǒng)優(yōu)化

2016-11-09 23:35:54

簡(jiǎn)易構(gòu)建風(fēng)控系統(tǒng)IP庫(kù)

2023-05-31 07:22:45

2024-10-07 08:40:56

Spring應(yīng)用程序Java

2022-11-09 07:20:15

MySQL性能管控

2017-09-01 15:05:23

網(wǎng)站性能互聯(lián)網(wǎng)DNS

2022-11-11 08:16:02

java性能技術(shù)

2017-05-19 22:46:36

多維后臺(tái)性能優(yōu)化手段
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)