最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

利用Redis如何實現(xiàn)自動補全功能

 更新時間:2019年09月10日 09:07:41   作者:阿飛的博客  
這篇文章主要給大家介紹了關(guān)于如何利用Redis如何實現(xiàn)自動補全功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

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

about sorted set

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

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

127.0.0.1:6380> zadd test 85 sida
127.0.0.1:6380> zadd test 80 xiaolang
127.0.0.1:6380> zadd test 60 afei
127.0.0.1:6380> zadd test 90 chenssy
127.0.0.1:6380> zadd test 98 yunaiv
127.0.0.1:6380> zrange test 0 -1
1) "afei"
2) "xiaolang"
3) "sida"
4) "chenssy"
5) "yunaiv"

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

127.0.0.1:6380> zadd exam 0 sida
127.0.0.1:6380> zadd exam 0 xiaolang
127.0.0.1:6380> zadd exam 0 chenssy
127.0.0.1:6380> zadd exam 0 yunaiv
127.0.0.1:6380> zadd exam 0 afei
127.0.0.1:6380> zrange exam 0 -1
1) "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) 2
127.0.0.1:6380> zrank exam yunaiv
(integer) 4
127.0.0.1:6380> zrange exam 2 4
1) "sida"
2) "xiaolang"
3) "yunaiv"

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

簡單實現(xiàn)

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

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

a, af, afe, afei, afei$

現(xiàn)在假設(shè)我們需要添加三個詞:foo, bar, foobar 來進(jìn)行一些測試, 那么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$"

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

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

更多詞的測試

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

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

時間&空間復(fù)雜度

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

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

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

那么需要多少內(nèi)存呢?

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

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

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

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

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

查詢預(yù)測

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

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

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

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

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

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

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

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

清理階段

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

知識總結(jié)

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

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

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • 基于?Redis?實現(xiàn)接口限流的方式

    基于?Redis?實現(xiàn)接口限流的方式

    今天想和小伙伴們聊聊用?Redis?處理接口限流,這也是最近的?TienChin?項目涉及到這個知識點了,我就拎出來和大家聊聊這個話題
    2022-05-05
  • Redis面試必備之緩存設(shè)計規(guī)范與性能優(yōu)化詳解

    Redis面試必備之緩存設(shè)計規(guī)范與性能優(yōu)化詳解

    你是否在使用Redis時,不清楚Redis應(yīng)該遵循的設(shè)計規(guī)范而苦惱,你是否在Redis出現(xiàn)性能問題時,不知道該如何優(yōu)化而發(fā)愁,快跟隨小編一起學(xué)習(xí)起來吧
    2024-03-03
  • Redis增減庫存避坑的實現(xiàn)

    Redis增減庫存避坑的實現(xiàn)

    在電商平臺或者倉庫管理系統(tǒng)中,庫存的管理是非常重要的一項任務(wù),本文主要介紹了Redis增減庫存避坑的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Java實現(xiàn)多級緩存的方法詳解

    Java實現(xiàn)多級緩存的方法詳解

    對于高并發(fā)系統(tǒng)來說,有三個重要的機制來保障其高效運行,它們分別是:緩存、限流和熔斷,所以本文就來和大家探討一下多級緩存的實現(xiàn)方法,希望對大家有所幫助
    2024-02-02
  • Redis實現(xiàn)延遲任務(wù)的三種方法詳解

    Redis實現(xiàn)延遲任務(wù)的三種方法詳解

    延遲任務(wù)(Delayed Task)是指在未來的某個時間點,執(zhí)行相應(yīng)的任務(wù),本文為大家整理了三種常見的實現(xiàn)方法,感興趣的小伙伴可以參考一下
    2025-04-04
  • 詳解如何在Windows上配置和使用Redis持久化功能

    詳解如何在Windows上配置和使用Redis持久化功能

    Redis 是一個強大的內(nèi)存數(shù)據(jù)庫,常用于緩存和實時數(shù)據(jù)處理,然而,由于其內(nèi)存特性,一旦服務(wù)器重啟或故障,存儲在 Redis 中的數(shù)據(jù)可能會丟失,為了確保數(shù)據(jù)的安全性和持久性,Redis 提供了多種持久化機制,本文將詳細(xì)介紹如何在 Windows 上配置和使用 Redis 的持久化功能
    2024-08-08
  • 深入理解Redis哈希槽

    深入理解Redis哈希槽

    Redis哈希槽是RedisCluster中實現(xiàn)數(shù)據(jù)分片和負(fù)載均衡的核心機制,本文就來介紹一下Redis哈希槽,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • Rocky9部署redis的實現(xiàn)示例

    Rocky9部署redis的實現(xiàn)示例

    本文主要介紹了Rocky9部署redis的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • 詳解三分鐘快速搭建分布式高可用的Redis集群

    詳解三分鐘快速搭建分布式高可用的Redis集群

    這篇文章主要介紹了詳解三分鐘快速搭建分布式高可用的Redis集群,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Spring Boot 項目集成Redis的方式詳解

    Spring Boot 項目集成Redis的方式詳解

    這篇文章主要介紹了Spring Boot 項目集成Redis的方式,本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧,需要的朋友可以參考下
    2021-08-08

最新評論

黔西| 温州市| 嘉祥县| 宜兴市| 丹寨县| 明溪县| 九江县| 聊城市| 卓资县| 临沧市| 靖西县| 太仆寺旗| 勃利县| 石楼县| 西安市| 湖北省| 北流市| 丰顺县| 乐都县| 新郑市| 万荣县| 安福县| 沙雅县| 卢氏县| 博湖县| 涡阳县| 康马县| 磴口县| 南丹县| 镇沅| 光泽县| 温泉县| 普洱| 塔河县| 龙江县| 东源县| 泸西县| 饶阳县| 烟台市| 苍南县| 宁武县|