一、需求緣起
某併發量很大,資料量適中的業務線需要實現乙個「標題檢索」的功能:
(1)併發量較大,每秒20w次
(2)資料量適中,大概200w資料
(3)是否需要分詞:是
(4)資料是否實時更新:否
二、常見潛在解決方案及優劣
(1)資料庫搜尋法
具體方法:將標題資料存放在資料庫中,使用like來檢索
優點:方案簡單
缺點:不能實現分詞,併發量扛不住
(2)資料庫全文檢索法
具體方法:將標題資料存放在資料庫中,建立全文索引來檢索
優點:方案簡單
缺點:併發量扛不住
(3)使用開源方案將索引外接
具體方法:搭建lucene,solr,es等開源外接索引方案
優點:效能比上面兩種好
缺點:併發量可能有風險,系統比較重,為乙個簡單的業務搭建一套這樣的系統成本較高
三、58龍哥的建議
問1:龍哥,58同城第一屆程式設計大賽的題目好像是「黃反詞過濾」,你是冠軍,當時是用dat來實現的麼?
龍哥:是的
畫外音:什麼是dat?
問2:上面的業務場景可以使用dat來實現麼?
龍哥:dat更新資料比較麻煩,不能增量
問3:那直接使用trie樹可以麼?
龍哥:trie樹比較佔記憶體
畫外音:什麼是trie樹?
例如:上面的trie樹就能夠表示{and, as, at, cn, com}這樣5個標題的集合。
問4:如果要支援分詞,多個分詞遍歷trie樹,還需要合併對吧?
龍哥:沒錯,每個分詞遍歷一次trie樹,可以得到doc_id的list,多個分詞得到的list合併,就是最終的結果。
問5:龍哥,還有什麼更好,更輕量級的方案麼?
龍哥:用trie樹,資料會膨脹文件數*標題長度這麼多,標題越長,文件數越多,記憶體占用越大。有個乙個方案,記憶體量很小,和標題長度無關,非常帥氣。
龍哥:可能網上沒有,我簡單說一下吧,核心思想就是「記憶體hash + id list」
索引初始化步驟為:對所有標題進行分詞,以詞的hash為key,doc_id的集合為value
查詢的步驟為:對查詢詞進行分詞,對分詞進行hash,直接查詢hash**,獲取doc_id的list,然後多個詞進行合併
*****例子*****
例如:doc1 : 我愛北京
doc2 : 我愛到家
doc3 : 到家美好
先標題進行分詞:
doc1 : 我愛北京 -> 我,愛,北京
doc2 : 我愛到家 -> 我,愛,到家
doc3 : 到家美好 -> 到家,美好
對分詞進行hash,建立hash + id list:
hash(我) ->
hash(愛) ->
hash(北京) ->
hash(到家) ->
hash(美好) ->
這樣,所有標題的初始化就完畢了,你會發現,資料量和標題的長度沒有關係。
使用者輸入「我愛」,分詞後變為,對各個分詞的hash進行記憶體檢索
hash(我)->
hash(愛)->
然後進行合併,得到最後的查詢結果是doc1+doc2。
*****例子end*****
問7:這個方法有什麼優點呢?
龍哥:存記憶體操作,能滿足很大的併發,時延也很低,占用記憶體也不大,實現非常簡單快速
問8:有什麼不足呢?和傳統搜尋有什麼區別咧?
龍哥:這是乙個快速過度方案,因為索引本身沒有落地,還是需要在資料庫中儲存固化的標題資料,如果不做高可用,資料恢復起來會比較慢。當然做高可用也是很容易的,建立兩份一樣的hash索引即可。另外,沒有做水平切分,但資料量非常非常非常大時,還是要做水平切分改進的。
通過Dapr快速落地DDD,實現高併發
ddd與dapr 提起ddd是不是感覺既熟悉又陌生,它很早就已經出現,但在軟體開發領域一直 雷聲大,雨點小 近幾年隨著微服務的流行,ddd又再一次引起人們的關注。領域驅動設計 domain driven design,簡稱ddd 是一種拆解業務 劃分業務 確定業務邊界的方法,具有一定的技術門檻,導致...
如何應對高併發?
參照乙個大佬的文章,我也寫一篇高併發的文章,一下這門高階的現象,以及一些解決措施。乙個關於高併發的問題 那位大佬說 如果真的幹過高併發系統的人,面試官是絕對不會對你提出這個問題的,否則就是他太不明智了。至於為嘛這樣說呢,因為如果設計乙個高併發系統,這句話就是錯誤的了,因為在脫離了業務的系統架構中都是...
高併發,如何提高併發量
一 什麼是高併發 高併發 high concurrency 是網際網路分布式系統架構設計中必須考慮的因素之一,它通常是指,通過設計保證系統能夠同時並行處理很多請求。高併發相關常用的一些指標有響應時間 response time 吞吐量 throughput 每秒查詢率qps query per se...