0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

百萬并發(fā)場(chǎng)景中倒排索引與位圖計(jì)算的實(shí)踐

OSC開源社區(qū) ? 來源:OSCHINA 社區(qū) ? 2023-01-10 10:35 ? 次閱讀

背景

Promise 時(shí)效控單系統(tǒng)作為時(shí)效域的控制系統(tǒng),在用戶下單前、下單后等多個(gè)節(jié)點(diǎn)均提供服務(wù),是用戶下單黃金鏈路上的重要節(jié)點(diǎn);控單系統(tǒng)主要邏輯是針對(duì)用戶請(qǐng)求從規(guī)則庫(kù)中找出符合條件的最優(yōu)規(guī)則,并將該規(guī)則的時(shí)效控制結(jié)果返回客戶端,比如因?yàn)榕R時(shí)疫情等原因針對(duì)倉(cāng)、配、商家、客戶四級(jí)地址等不同維度進(jìn)行精細(xì)粒度的時(shí)效控制。 該系統(tǒng)也是 Promise 側(cè)并發(fā)量最大的系統(tǒng),雙 11 高峰集群流量 TPS 在百萬級(jí)別,對(duì)系統(tǒng)的性能要求非常高,SLA 要求在 5ms 以內(nèi),因此對(duì)海量請(qǐng)求在規(guī)則庫(kù) (幾十萬) 中如何快速正確匹配規(guī)則是該系統(tǒng)的技術(shù)挑戰(zhàn)點(diǎn)。

樸素的解決方案

按照樸素的思想,在工程建設(shè)上,通過異步方式將規(guī)則庫(kù)逐行緩存到 Redis,Key 為規(guī)則條件,Value 為規(guī)則對(duì)應(yīng)結(jié)果;當(dāng)用戶請(qǐng)求過來時(shí),對(duì)請(qǐng)求 Request (a,b,c,d..) 中的參數(shù)做全組合,根據(jù)全組合出的 Key 嘗試找出所有可能命中的規(guī)則,再?gòu)闹泻Y選出最優(yōu)的規(guī)則。如下圖所示

3872ffc4-902a-11ed-bfe3-dac502259ad0.png

該方案面臨的問題是全組合的時(shí)間復(fù)雜度是 2**n,n≈12;算法的時(shí)間復(fù)雜度高且算法穩(wěn)定性差,最差情況一次請(qǐng)求需要 4096 次計(jì)算和讀取操作。當(dāng)然在工程上我們可以使用本地緩存做一些優(yōu)化,但是無法解決最根本的性能問題。架構(gòu)簡(jiǎn)圖如下所示:

389ae19c-902a-11ed-bfe3-dac502259ad0.png

新的解決方案

上面方案是從行的角度看待匹配定位的,能夠命中的行的每一列必然也是符合條件的,這里面存在某種隱約的內(nèi)在聯(lián)系。能否反過來思考這個(gè)問題,為此我們嘗試進(jìn)行新的方案,當(dāng)然架構(gòu)簡(jiǎn)圖依然如上圖所示,核心優(yōu)化的是命中算法。 新的方案整體采用列的倒排索引和倒排索引位運(yùn)算的方式,使得計(jì)算復(fù)雜度由原來的 2n 降至 n**,且算法穩(wěn)定性有非常好的保證。其中列的倒排索引是對(duì)每列的值和所分布的行 ID (即 Posting List) 建立 KV 關(guān)系,倒排索引位運(yùn)算是對(duì)符合條件的列倒排索引進(jìn)行列間的位運(yùn)算,即通過聯(lián)合查詢以便快速找到符合條件的規(guī)則行。

算法詳細(xì)設(shè)計(jì)

1. 預(yù)計(jì)算生成列的倒排索引和位圖

通過對(duì)每列的值進(jìn)行分組合并生成 Posting List,建立列值和 Posting List 的 KV 關(guān)系。以下圖為例,列 A 可生成的倒排索引為:301={1},201={2,3,4,5} 等,需要說明的一點(diǎn),空值也是一種候選項(xiàng),也需要生成 KV 關(guān)系,如 nil={7}。

38b07b2e-902a-11ed-bfe3-dac502259ad0.png

2. 生成列的倒排索引對(duì)應(yīng)位圖

將步驟 1 的倒排索引轉(zhuǎn)成成位圖,方便后續(xù)的位圖計(jì)算,轉(zhuǎn)換規(guī)則為行 ID 對(duì)應(yīng)位圖的下標(biāo)位(步驟 1、2 可以合并操作)。

38d8b4ea-902a-11ed-bfe3-dac502259ad0.png

3. 根據(jù)用戶請(qǐng)求查找列位圖,通過位圖計(jì)算生成候選規(guī)則集

將用戶請(qǐng)求中的入?yún)⒆鳛?Key,查找符合條件的位圖,對(duì)每一列進(jìn)行列內(nèi)和空值做 || 運(yùn)算,最后列間位圖做 & 運(yùn)算,得到的結(jié)果是候選規(guī)則集,如下圖所示:

38eac7ac-902a-11ed-bfe3-dac502259ad0.png

4. 從候選規(guī)則庫(kù)中,根據(jù)業(yè)務(wù)優(yōu)先級(jí)排序,查找最優(yōu)的規(guī)則

以候選規(guī)則為基點(diǎn),按照業(yè)務(wù)優(yōu)先級(jí)排序,進(jìn)行逐級(jí)位運(yùn)算 &,當(dāng)遍歷完或位運(yùn)算為 0 時(shí),找到最后不為空的即為最優(yōu)規(guī)則,該過程是從候選規(guī)則庫(kù)逐漸縮小最優(yōu)范圍的過程。需要說明某列當(dāng)用戶請(qǐng)求位圖不存在時(shí),需要使用對(duì)應(yīng)的空位圖進(jìn)行參與,以 B 列為例,入?yún)?B_1102 不存在,需要使用 B_nil 參與 &。

392a8338-902a-11ed-bfe3-dac502259ad0.png

復(fù)雜度分析

通過上面的例子我們可以看到,在時(shí)間復(fù)雜度方面查找候選規(guī)則集時(shí),進(jìn)行一輪 || 運(yùn)算,一輪 & 運(yùn)算;在查找最優(yōu)規(guī)則時(shí)進(jìn)行一輪 & 運(yùn)算,所以整體復(fù)雜度是 3n≈n。 在空間復(fù)雜度方面,相比原來的行式存儲(chǔ),倒排索引的存儲(chǔ)方式,每列都需要存儲(chǔ)行 ID,相當(dāng)于多了 *(n-1)Posting List 存儲(chǔ)空間,當(dāng)然這是粗略計(jì)算,因?yàn)閷?shí)際上行 ID 的存儲(chǔ)最終轉(zhuǎn)換為位圖存儲(chǔ),在空間上有非常大的壓縮空間。

工程問題 - 壓縮位圖

如果倒排索引位圖非常稀疏,系統(tǒng)會(huì)存在非常大的空間浪費(fèi)。我們舉一個(gè)極端 case,若千萬規(guī)則庫(kù)中命中的行 ID 是第 1000 萬位,按照傳統(tǒng)方式 BitSet 進(jìn)行存儲(chǔ),需要消耗 1.2MB 空間,在內(nèi)存中占用存在嚴(yán)重浪費(fèi),有沒有壓縮優(yōu)化方案,在 RoaringBitMap 壓縮位圖方案中我們找到,相同場(chǎng)景在壓縮位圖方式下僅占 144bytes;即使在 1000 萬的位圖空間,我們隨機(jī)存儲(chǔ) 1 萬個(gè)值,兩者比也是在 31K vs 2MB,近 100 倍的差距,總的來說 RoaringBitMap 壓縮率非常大。 RoaringBitMap 本質(zhì)上是將大塊的 bitmap 拆分成各個(gè)小塊,其中每個(gè)小塊在需要存儲(chǔ)數(shù)據(jù)的時(shí)候才會(huì)存在,所以當(dāng)進(jìn)行交集或并集運(yùn)算的時(shí)候,RoaringBitMap 只需要去計(jì)算存在的塊而不需要像 bitmap 那樣對(duì)整個(gè)大塊進(jìn)行計(jì)算,既做到了壓縮的存儲(chǔ)又做到計(jì)算性能的提升。 以下圖 821697800 為例,對(duì)應(yīng)的 16 進(jìn)制數(shù)為 30FA1D08, 其中高 16 位為 30FA,低 16 位為 1D08。先用二分查找從一級(jí)索引(即 Container Array)中找到數(shù)值為 30FA 的容器,該容器是一個(gè) Bitmap 容器,然后在該容器查找低 16 位的數(shù)值 1D08,即十進(jìn)制下 7432,在 Bitmap 中找到相應(yīng)的位置,將其置為 1 即可。

3970defa-902a-11ed-bfe3-dac502259ad0.png

適用場(chǎng)景分析

回顧上面的設(shè)計(jì)方案我們可以看到,這種方式僅適用于 PostingList 簡(jiǎn)單如行 ID 的形式,如果是復(fù)雜對(duì)象就不適合用位圖來存儲(chǔ)。另外僅適用于等值查詢,不適用于 like、in 的范圍查詢,為什么有這種局限性?因?yàn)檫@種方式依賴于搜索條件的空間,在方案中我們將值的條件作為搜索的 Key,值的條件空間希望盡可能是一個(gè)有限的、方便窮舉的、小的空間。而范圍查詢導(dǎo)致這個(gè)空間變成難以窮舉、近乎無限擴(kuò)張的、所以不適用。

其他優(yōu)化方式

除了使用位運(yùn)算的方式對(duì)倒排索引加速,考慮到 Posting List 的有序性,還有其他的方式比如使用跳表、Hash 表等方式,以 ES 中采用的跳表為例,進(jìn)行 & 運(yùn)算實(shí)際就是在查找兩個(gè)有序 Posting List 公共部分,以相互二分查找的形式,將時(shí)間復(fù)雜度控制在 log (n) 的級(jí)別。 具體參見《工業(yè)界如何利用跳表、哈希表、位圖進(jìn)行倒排索引加速?》:https://time.geekbang.org/column/article/221292?utm_source=related_read&utm_medium=article&utm_term=related_read

399ab9be-902a-11ed-bfe3-dac502259ad0.png

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 索引
    +關(guān)注

    關(guān)注

    0

    文章

    59

    瀏覽量

    10446
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    368

    瀏覽量

    10780
  • 位圖
    +關(guān)注

    關(guān)注

    0

    文章

    6

    瀏覽量

    2244

原文標(biāo)題:百萬并發(fā)場(chǎng)景中倒排索引與位圖計(jì)算的實(shí)踐

文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    MATLAB的矩陣索引

    對(duì)矩陣進(jìn)行索引是從矩陣中選擇或修改部分元素的一種方式。MATLAB 有幾種索引樣式,它們不僅功能強(qiáng)大、靈活,而且可讀性強(qiáng)、表現(xiàn)力強(qiáng)。矩陣是 MATLAB 用來組織和分析數(shù)據(jù)的一個(gè)核心組件,索引是以可理解的方式有效操作矩陣的關(guān)鍵。
    的頭像 發(fā)表于 09-05 09:28 ?196次閱讀
    MATLAB<b class='flag-5'>中</b>的矩陣<b class='flag-5'>索引</b>

    TRIZ在逆變器設(shè)計(jì)實(shí)踐應(yīng)用

    基于數(shù)百萬個(gè)專利案例的分析,提煉出一套系統(tǒng)化、結(jié)構(gòu)化的創(chuàng)新工具,幫助人們?cè)诿鎸?duì)復(fù)雜問題時(shí),能夠迅速找到最優(yōu)解決方案。今天,就讓我們一起探索TRIZ在逆變器設(shè)計(jì)實(shí)踐應(yīng)用,見證科技如何重塑能源轉(zhuǎn)換的每一個(gè)細(xì)節(jié)。 1. 提升效率,
    的頭像 發(fā)表于 08-23 11:16 ?231次閱讀

    ClickHouse內(nèi)幕(3)基于索引的查詢優(yōu)化

    ClickHouse索引采用唯一聚簇索引的方式,即Part內(nèi)數(shù)據(jù)按照order by keys有序,在整個(gè)查詢計(jì)劃,如果算子能夠有效利用輸入數(shù)據(jù)的有序性,對(duì)算子的執(zhí)行性能將有巨大的提升。本文討論
    的頭像 發(fā)表于 06-11 10:46 ?728次閱讀
    ClickHouse內(nèi)幕(3)基于<b class='flag-5'>索引</b>的查詢優(yōu)化

    【大語(yǔ)言模型:原理與工程實(shí)踐】探索《大語(yǔ)言模型原理與工程實(shí)踐》2.0

    《大語(yǔ)言模型“原理與工程實(shí)踐”》是關(guān)于大語(yǔ)言模型內(nèi)在機(jī)理和應(yīng)用實(shí)踐的一次深入探索。作者不僅深入討論了理論,還提供了豐富的實(shí)踐案例,幫助讀者理解如何將理論知識(shí)應(yīng)用于解決實(shí)際問題。書中的案例分析有助于
    發(fā)表于 05-07 10:30

    鴻蒙原生應(yīng)用開發(fā)-ArkTS語(yǔ)言基礎(chǔ)類庫(kù)多線程并發(fā)概述

    并發(fā)模型是用來實(shí)現(xiàn)不同應(yīng)用場(chǎng)景并發(fā)任務(wù)的編程模型,常見的并發(fā)模型分為基于內(nèi)存共享的并發(fā)模型和基
    發(fā)表于 03-22 15:40

    邊緣計(jì)算物聯(lián)網(wǎng)關(guān)在生產(chǎn)場(chǎng)景的應(yīng)用

    隨著物聯(lián)網(wǎng)技術(shù)的飛速發(fā)展,邊緣計(jì)算物聯(lián)網(wǎng)關(guān)在生產(chǎn)場(chǎng)景的應(yīng)用越來越廣泛。邊緣計(jì)算物聯(lián)網(wǎng)關(guān)作為連接物理世界與數(shù)字世界的橋梁,能夠?qū)鞲衅?、?zhí)行器等設(shè)備產(chǎn)生的海量數(shù)據(jù)實(shí)時(shí)傳輸?shù)皆贫诉M(jìn)行處理
    的頭像 發(fā)表于 02-28 15:49 ?390次閱讀

    導(dǎo)致MySQL索引失效的情況以及相應(yīng)的解決方法

    的解決方法。 1. 索引列被函數(shù)操作 如果在查詢條件對(duì)索引列使用了函數(shù)操作,例如使用了函數(shù)進(jìn)行聚合、類型轉(zhuǎn)換或者字符串操作,那么索引將無法發(fā)揮作用。例如,使用了LOWER函數(shù)對(duì)
    的頭像 發(fā)表于 12-28 10:01 ?634次閱讀

    Mysql索引是什么東西?索引有哪些特性?索引是如何工作的?

    作為開發(fā)人員,碰到了執(zhí)行時(shí)間較長(zhǎng)的 sql 時(shí),基本上大家都會(huì)說” 加個(gè)索引吧”。但是索引是什么東西,索引有哪些特性,下面和大家簡(jiǎn)單討論一下。
    的頭像 發(fā)表于 12-24 16:20 ?972次閱讀
    Mysql<b class='flag-5'>索引</b>是什么東西?<b class='flag-5'>索引</b>有哪些特性?<b class='flag-5'>索引</b>是如何工作的?

    磁盤RocketMQ構(gòu)建的索引結(jié)構(gòu)

    RocketMQ 廣泛使用于各類業(yè)務(wù)場(chǎng)景,在實(shí)際生產(chǎn)場(chǎng)景,用戶通常會(huì)選擇消息 ID 或者特定的業(yè)務(wù) Key(例如學(xué)號(hào),訂單號(hào))來查詢和定位特定的一批消息,進(jìn)而定位分布式系統(tǒng)
    的頭像 發(fā)表于 12-22 10:43 ?318次閱讀
    磁盤<b class='flag-5'>中</b>RocketMQ構(gòu)建的<b class='flag-5'>索引</b>結(jié)構(gòu)

    什么場(chǎng)景需要jvm調(diào)優(yōu)

    JVM調(diào)優(yōu)是指對(duì)Java虛擬機(jī)進(jìn)行性能優(yōu)化和資源管理,以提高應(yīng)用程序的運(yùn)行效率和吞吐量。JVM調(diào)優(yōu)的場(chǎng)景有很多,下面將詳細(xì)介紹各種不同的場(chǎng)景。 高并發(fā)場(chǎng)景:在高
    的頭像 發(fā)表于 12-05 11:14 ?1085次閱讀

    服務(wù)器并發(fā)的概念

    在編寫服務(wù)器時(shí),如果服務(wù)器的設(shè)計(jì)初衷是要可以承擔(dān)百萬、千萬的客戶端連接,那么默認(rèn)的情況下,Linux操作系統(tǒng)提供的相關(guān)配置參數(shù)(比如說進(jìn)程可分配的文件數(shù)目等)是不能夠滿足我們的程序需求的,因此需要
    的頭像 發(fā)表于 11-10 10:05 ?2490次閱讀
    服務(wù)器<b class='flag-5'>并發(fā)</b>的概念

    索引的底層實(shí)現(xiàn)詳解

    說一說索引的底層實(shí)現(xiàn)? Hash索引 基于哈希表實(shí)現(xiàn),只有精確匹配索引所有列的查詢才有效,對(duì)于每一行數(shù)據(jù),存儲(chǔ)引擎都會(huì)對(duì)所有的索引計(jì)算一個(gè)
    的頭像 發(fā)表于 10-09 10:26 ?648次閱讀
    <b class='flag-5'>索引</b>的底層實(shí)現(xiàn)詳解

    索引是什么意思 優(yōu)缺點(diǎn)有哪些

    的數(shù)據(jù)結(jié)構(gòu),以協(xié)助快速查詢、更新數(shù)據(jù)庫(kù)表數(shù)據(jù)。索引的實(shí)現(xiàn)通常使用B樹及其變種B+樹。更通俗的說,索引就相當(dāng)于目錄。為了方便查找書中的內(nèi)容,通過對(duì)內(nèi)容建立索引形成目錄。而且
    的頭像 發(fā)表于 10-09 10:19 ?2461次閱讀

    mysql數(shù)據(jù)庫(kù)索引失效的10種場(chǎng)景

    今天就跟大家一起聊聊,mysql數(shù)據(jù)庫(kù)索引失效的10種場(chǎng)景,給曾經(jīng)踩過坑,或者即將要踩坑的朋友們一個(gè)參考。 1. 準(zhǔn)備工作 所謂空口無憑,如果我直接把索引失效的這些場(chǎng)景丟出來,可能沒有
    的頭像 發(fā)表于 10-07 16:31 ?1214次閱讀
    mysql數(shù)據(jù)庫(kù)<b class='flag-5'>索引</b>失效的10種<b class='flag-5'>場(chǎng)景</b>

    MySQL索引的常用知識(shí)點(diǎn)

    索引結(jié)構(gòu):B+樹 索引其實(shí)是一種數(shù)據(jù)結(jié)構(gòu) 注意B+樹是MySQL,索引默認(rèn)的結(jié)構(gòu);一張表至少有一個(gè)索引(主鍵索引),是可以有多個(gè)
    的頭像 發(fā)表于 09-30 16:43 ?374次閱讀