麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 數據庫 > Redis > 正文

利用Redis如何實現自動補全功能

2020-10-28 21:29:07
字體:
來源:轉載
供稿:網友

忘了redis從哪個版本開啟,能夠根據輸入的部分命令前綴給出提示,即自動補全。接下來筆者介紹基于redis實現這個很酷的功能。

about sorted set

假設結果中有mara,marabel,marcela。現在我們輸入mar,就能得到這三個名字,并且輸出結果按照字典排序。在實現這個需求之間,我們先簡單介紹sorted set。

大家都知道sorted set是按照score排序的:

127.0.0.1:6380> zadd test 85 sida127.0.0.1:6380> zadd test 80 xiaolang127.0.0.1:6380> zadd test 60 afei127.0.0.1:6380> zadd test 90 chenssy127.0.0.1:6380> zadd test 98 yunaiv127.0.0.1:6380> zrange test 0 -11) "afei"2) "xiaolang"3) "sida"4) "chenssy"5) "yunaiv"

但是如果score都一樣,sorted set是按照什么排序的呢?是按照字典排序的:

127.0.0.1:6380> zadd exam 0 sida127.0.0.1:6380> zadd exam 0 xiaolang127.0.0.1:6380> zadd exam 0 chenssy127.0.0.1:6380> zadd exam 0 yunaiv127.0.0.1:6380> zadd exam 0 afei127.0.0.1:6380> zrange exam 0 -11) "afei"2) "chenssy"3) "sida"4) "xiaolang"5) "yunaiv"

這是sorted set一個非常重要的特性,也是我們自動補全需求的一個要點。但是這還不夠,離我們的最終需求還有一段路要走。幸運的是sorted set還有另一個很酷的命令:ZRANK。這個命令能知道你要查詢的key在sorted set中的位置:

127.0.0.1:6380> zrank exam sida(integer) 2127.0.0.1:6380> zrank exam yunaiv(integer) 4127.0.0.1:6380> zrange exam 2 41) "sida"2) "xiaolang"3) "yunaiv"

到這里感覺離我們實現自動補全的第一個版本非常接近了,我們能得到sorted set中按照字典排序后任意一個member及其后面N個member。

簡單實現

為了實現最終的自動補全,我們需要付出一些代價:空間。

意思是,對于某個準備添加到sorted set中的member,例如afei,我們不僅要把完整的詞(afei)添加到sorted set中,而且還要添加所有可能的前綴(a, af, afe, afei)。這里為了解決某個詞是真正的member還是某個member的前綴(例如bar既是一個完整的詞,也是某個member例如bark的可能前綴),我們加了一個小把戲,即在真正member的后面增加一個特殊字符,例如"$",那么afei這個member就會添加下列這些詞:

a, af, afe, afei, afei$

現在假設我們需要添加三個詞:foo, bar, foobar 來進行一些測試, 那么sorted set中就會有如下這些詞:

127.0.0.1:6380> zrange autoc 0 -1 1) "b" 2) "ba" 3) "bar" 4) "bar$" 5) "f" 6) "fo" 7) "foo" 8) "foo$" 9) "foob"10) "fooba"11) "foobar"12) "foobar$"

離我們最終的目標又要近了很多。現在假設用戶輸入"fo",那么為了實現自動補全,我們需要執行如下命令,仔細查看結果,foo$和foobar$就是我們需要的結果,只需要將特殊后綴$去掉即可(其他沒有以$結尾的詞全部忽略):

127.0.0.1:6380> zrank autoc fo(integer) 5127.0.0.1:6380> zrange autoc 5 -11) "fo"2) "foo"3) "foo$"4) "foob"5) "fooba"6) "foobar"7) "foobar$"

更多詞的測試

網址http://antirez.com/misc/female-names.txt 提供了近5000個女性名字。按照前面說的規則,將所有名字的所有可能前綴全部添加到sorted set中。假定用戶輸入member,那么只需要通過如下兩個命令,得到字典排序后用戶輸入的member后面的50個詞,然后只取$結尾的詞:

127.0.0.1:6380> zrank autoc member(integer) 8127.0.0.1:6380> zrange autoc 8 50

時間&空間復雜度

根據官方文檔可知,zrank和zrange的事件復雜度都是O(log(N))。因此,即使數據量比較大,這種方案也是可行的。

ZRANK key member
起始版本:2.0.0
時間復雜度:O(log(N))

ZRANGE key start stop [WITHSCORES]
起始版本:1.2.0
時間復雜度:O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned.

那么需要多少內存呢?

假設在最糟糕的情況下,一個長度為M的詞需要添加M+1個詞到sorted set中。那么如果有N個詞,總計需要添加N*(Ma+1)個詞到sorted set中,Ma是這N個詞的平均長度。

幸運的是,實際情況遠比這個要好得多,以近5000個女性名字為例,只需要添加大約15000個詞到sorted set中,因為這些名詞存在大量重復的前綴。以3個名字為例:marci,marcia,marcile。如果按照最糟糕的情況,需要添加3*(6+1)=21個詞到sorted set中,然而實際情況呢,只需要添加11個詞到sorted set中即可:

m, ma , mar, marc, marci, marci$, marcia, marcia$, marcil, marcile, marcile$。

而且,隨著樣本越來越大,重復的前綴會越大越多。

所以,需要的內存也還OK。是不是覺得美滋滋?哈

查詢預測

我們這次的自動補全是按照字典排序,很多時候,這是我們需要的。但是也有一些情況,我們希望按照相似度來排序。例如google搜索那樣,搜索結果按照頻率和熱度等維度進行排序。例如,當用戶輸入ne,用戶應該希望看到Netflix,news,new york times等這些熱門關鍵詞。

這樣做起來就不那么容易了,如果要能達到根據頻率排序,我們需要一個特別的sorted set能以非阻塞的方式實時更新每個前綴的頻率:

當用戶輸入一個例如"foo"這種查詢,由于它的所有前綴為:"f", "fo", "foo"。那么對每個前綴都執行命令:ZINCRBY <prefix> 1 foo ;如果用戶輸入"foobar",那么對每個前綴都執行:ZINCRBY <prefix> 1 foobar;

這種方法還有一個問題,許多自動補全系統只需要展示TOP N個關鍵詞,假設N為10。但是我們這種方法,如果要計算TOP 10,我們需要取得關鍵詞遠不止10個,理論上我們要這個前綴作為key的sorted set中所有member都取出來。

幸運的是,從統計學上來講,每個對于sorted set中有300個member的前綴,就能得到TOP 5關鍵詞。如果查詢越頻繁,它的得分越高,它最終被選中的概率也就越高。因此,我們要做的就是對搜索字符串的每個前綴:

  • 如果前綴作為key的sorted set中member數量還沒有達到300,那么只需要簡單的對其zincrby即可;
  • 如果前綴作為key的sorted set中member數量已經達到了300,我們將那些得分比較低的member刪除,增加新的member進來,從而達到關鍵詞頻率不斷迭代的效果。

這個方法一下子可能理解不過來,沒關系,舉個栗子。假設現在用戶輸入了next,其前綴n為key的sorted set中已經有netflix(100), news(120), new york(80), near(23), nequ(1)。由于這個前綴對應的sorted set中的member數量還沒有300,所以,執行:zincrby n 1 next。其中n是前綴,next是用戶輸入的關鍵詞。假設現在用戶輸入了next,其前綴n為key的sorted set中已經有netflix(100), news(120), new york(80), near(23), 省略295個score大于1的關鍵詞, nequ(1)。由于這個前綴對應的sorted set中的member數量達到了300,所以,先刪除得分比較低的nequ,再執行:zincrby n 1 next。

這個方法跟用戶輸入關鍵詞分布有很大的關聯性,如果用戶輸入的所有關鍵詞頻率比較接近,那么這個方法得到的數據并不是很可靠。但是我們知道這不是問題,因為搜索就是絕大部分人在搜索那一小部分關鍵詞集合。

清理階段

由于上面提到的搜索長尾效應,我們可以講那些得分為1的member清理掉,因為用戶對這些關鍵詞幾乎沒有任何關注度。清理操作還能夠減少使用內存,從而讓redis保存更多更有用的數據。

知識總結

  • sorted set數據結構中,如果member的score一樣,那么按照字典排序。
  • zrank命令能得到指定member在結果中的位置,并可以取排在它后面N個member。
  • zincrby能給指定的sorted set中的member加分。

參考:http://oldblog.antirez.com/post/autocomplete-with-redis.html

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 中文字幕网址 | 逼特逼视频在线观看 | 国产精品久久久久久影视 | 717影院理论午夜伦八戒秦先生 | 性欧美极品xxxx欧美一区二区 | 羞羞视频免费网站含羞草 | 日本网站在线看 | 国产一级免费在线视频 | 在线观看中文字幕国产 | 亚洲91网站 | 亚洲免费毛片基地 | 成人mm视频在线观看 | 免费一级a毛片免费观看 | 精品一区二区三区日本 | 一级大黄毛片免费观看 | 爱草在线 | 欧美一级淫片免费播放口 | 欧美中文字幕在线视频 | 欧美城网站地址 | 一级网站片 | 国产精品成人免费一区久久羞羞 | 污污短视频 | 九九热精品免费视频 | www嫩草| 久久福利小视频 | 国产一级一片免费播放 | 大胆在线日本aⅴ免费视频 美国黄色毛片女人性生活片 | 99精品视频久久精品视频 | 国产午夜精品久久久久婷 | 在线免费观看麻豆 | 精品亚洲va在线va天堂资源站 | 91av在线影院| 精品国产91久久久久 | 中文字幕电影免费播放 | 九九热免费在线观看 | 高清国产午夜精品久久久久久 | 美女黄色影院 | 日韩黄色片免费看 | 免费在线观看午夜视频 | 亚洲精品久久久久久下一站 | 高清视频一区二区 |