Redis的數據類型及特點有哪些

小編給大家分享一下redis的數據類型及特點有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

武川網站建設公司創新互聯建站,武川網站設計制作,有大型網站制作公司豐富經驗。已為武川1000多家提供企業網站建設服務。企業網站搭建\外貿網站建設要多少錢,請找那個售后服務好的武川做網站的公司定做!

Redis為我們提供了5種數據類型,基本上我們使用頻率***的就是String,而對其他四種數據類型使用的頻次稍弱于String。原因在于:

  • String使用起來比較簡單,可以方便存儲復雜的對象,使用場景比較多;

  • 由于Redis expire  time只能設置在key上,像List、Hash、Set、Zset屬于集合類型,會管理一組item,我們無法在這些集合的item上設置過期時間,所以使用expiretime來處理集合的cache失效會變得稍微復雜些。但是String使用expire  time來管理過期策略會比較簡單,因為它包含的項少。這里說的集合是寬泛的類似集合。

  • 從更深層次來看,我們對另外四種數據類型的使用和原理并不是太了解。所以這個時候往往會忽視在特定場景下使用某種數據類型會比String性能高出很多的可能性,比如使用Hash結構來提高某實體某個項的修改等。

這里我們不打算羅列這5種數據類型的使用方法,因為這些資料網上有很多。我們主要討論這5種數據類型的功能特點,弄清楚它們分別適合用于處理哪些現實的業務場景,我們又該如何組合性使用這5種數據類型,找到解決復雜cache問題的***方案。

一、Redis的數據類型及特點

我們來簡要了解一下String、List、Hash、Set及Zset:

1)String

String是Redis提供的字符串類型。可以針對String類型獨立設置expire  time,通常用來存儲長字符串數據,比如某個對象的json字符串。

在使用上,String類型最巧妙的是可以動態拼接key。通常我們可以將一組id放在Set里,然后動態查找String還是否存在,如果不存在說明已經過期或者由于數據修改主動delete了,需要再做一次cache數據load。

雖然Set無法設置item的過期時間,但是我們可以將Set Item與String Key關聯來達到相同的效果。

下圖中的左邊是一個key為Set:order:ids的Set集合,它可能是一個全量集合,也可能是某個查詢條件獲取出來的一個集合:

Redis的數據類型及特點有哪些

有時候復雜點的場景需要多個Set集合來支撐計算,在Redis服務器里可能會有很多類似這樣的集合。這些集合我們可以稱為功能數據,這些數據是用來輔助cache計算的,當進行各種集合運算之后會得出當前查詢需要返回的子集,***我們才會去獲取某個訂單真正的數據。

這些String:order:{orderId}字符串key并不一定是為了服務一種場景,而是整個系統***層的數據,各種場景***都需要獲取這些數據。那些Set集合可以認為是查詢條件數據,用來輔助查詢條件的計算。

Redis為我們提供了TYPE命令來查看某個key的數據類型,如String類型:

SET string:order:100 order-100  TYPE string:order:100  string

2)List

List在提高throughput的場景中非常適用,因為它特有的LPUSH、RPUSH、LPOP、RPOP功能可以無縫的支持生產者、消費者架構模式。

這非常適合實現類似Java Concurrency Fork/Join框架中的work-stealing算法(工作竊取)。

注:Java Fork/Join框架使用并行來提高性能,但是會帶來由于并發take task帶來的race  condition(競態條件)問題,所以采用work-stealing算法來解決由于競爭問題帶來的性能損耗。

下圖中模擬了一個典型的支付callback峰值場景:

Redis的數據類型及特點有哪些

在峰值出現的地方一般我們都會使用加buffer的方式來加快請求處理速度,這樣才能提高并發處理能力,提高through put。

支付gateway收到callback之后不做任何處理直接交給分發器。

分發器是一個無狀態的cluster,每個node通過向注冊中心pull handler queue  list,也就是獲取下游處理器注冊到注冊中心里的消息通道。每一個分發器node會維護一個本地queue list,然后順序推送消息到這些queue  list即可。

這里會有點小問題,就是支付gateway調用分發器的時候,是如何做load balance?如果不是平均負載可能會有某個queue  list高出其他queue list。

而分發器不需要做soft load balance,因為哪怕某個queue list比其他queue list多也無所謂,因為下游message  handler會根據work-stealing算法來竊取其他消費慢的queue list。

Redis List的LPUSH、RPUSH、LPOP、RPOP特性確實可以在很多場景下提高這種橫向擴展計算能力。

3)Hash

Hash數據類型很明顯是基于Hash算法的,對于項的查找時間復雜度是O(1)的,在極端情況下可能出現項Hash沖突問題,Redis內部是使用鏈表加key判斷來解決的。具體Redis內部的數據結構我們在后面有介紹,這里就不展開了。

Hash數據類型的特點通常可以用來解決帶有映射關系,同時又需要對某些項進行更新或者刪除等操作。如果不是某個項需要維護,那么一般可以通過使用String來解決。

如果有需要對某個字段進行修改,使用String很明顯會多出很多開銷,需要讀取出來反序列化成對象然后操作,然后再序列化寫回Redis,這中間可能還有并發問題。

那我們可以使用Redis Hash提供的實體屬性Hash存儲特性,我們可以認為Hash Value是一個Hash  Table,實體的每一個屬性都是通過Hash得到屬性的最終數據索引。

下圖使用Hash數據類型來記錄頁面的a/bmetrics:

Redis的數據類型及特點有哪些

左邊的是首頁index的各個區域的統計,右邊是營銷marketing的各個區域統計。

在程序里我們可以很方便的使用Redis的atomic特性對Hash某個項進行累加操作。

HMSET hash:mall:page:ab:metrics:index topbanner 10 leftbanner 5 rightbanner 8 bottombanner 20 productmore 10 topshopping 8  OK  HGETALL hash:mall:page:ab:metrics:index   1) "topbanner"   2) "10"   3) "leftbanner"   4) "5"   5) "rightbanner"   6) "8"   7) "bottombanner"   8) "20"   9) "productmore"  10) "10"  11) "topshopping"  12) "8" HINCRBY hash:mall:page:ab:metrics:index topbanner 1(integer) 11

使用Redis Hash  Increment進行原子增加操作。HINCRBY命令可以原子增加任何給定的整數,也可以通過HINCRBYFLOAT來原子增加浮點類型數據。

4)Set

Set集合數據類型可以支持集合運算,不能存儲重復數據。

Set***的特點就是集合的計算能力,inter交集、union并集、diff差集,這些特點可以用來做高性能的交叉計算或者剔除數據。

Set集合在使用場景上還是比較多和自由的。舉個簡單的例子,在應用系統中比較常見的就是商品、活動類場景。用一個Set緩存有效商品集合,再用一個Set緩存活動商品集合。如果商品出現上下架操作只需要維護有效商品Set,每次獲取活動商品的時候需要過濾下是否有下架商品,如果有就需要從活動商品中剔除。

當然,下架的時候可以直接刪除緩存的活動商品,但是活動是從marketing系統中load出來的,就算我將cache里的活動商品刪除,當下次再從marketing系統中load活動商品時候還是會有下架商品。

當然這只是舉例,一個場景有不同的實現方法。

下圖中左右兩邊是兩個不同的集合:

Redis的數據類型及特點有哪些

左邊是營銷域中的可用商品ids集合,右邊是營銷域中活動商品ids集合,中間計算出兩個集合的交集。

SADD set:marketing:product:available:ids 1000100 1000120 1000130 1000140 1000150 1000160   SMEMBERS set:marketing:product:available:ids  1) "1000100"  2) "1000120"  3) "1000130"  4) "1000140"  5) "1000150"  6) "1000160"   SADD set:marketing:activity:product:ids 1000100 1000120 1000130 1000140 1000200 1000300   SMEMBERS set:marketing:activity:product:ids  1) "1000100"  2) "1000120"  3) "1000130"  4) "1000140"  5) "1000200"  6) "1000300"   SINTER set:marketing:product:available:ids set:marketing:activity:product:ids  1) "1000100"  2) "1000120"  3) "1000130"  4) "1000140"

在一些復雜的場景中,也可以使用SINTERSTORE命令將交集計算后的結果存儲在一個目標集合中。這在使用pipeline命令管道中特別有用,將SINTERSTORE命令包裹在pipeline命令串中可以重復使用計算出來的結果集。

由于Redis是Signle-Thread單線程模型,基于這個特性我們就可以使用Redis提供的pipeline管道來提交一連串帶有邏輯的命令集合,這些命令在處理期間不會被其他客戶端的命令干擾。

5)Zset

Zset排序集合與Set集合類似,但是Zset提供了排序的功能。在介紹Set集合的時候我們知道Set集合中的成員是無序的,Zset填補了集合可以排序的空隙。

Zset***大的功能就是可以根據某個score比分值進行排序,這在很多業務場景中非常急需。比如,在促銷活動里根據商品的銷售數量來排序商品,在旅游景區里根據流入人數來排序熱門景點等?;旧先藗冊谧鋈魏问虑槎夹枰鶕承l件進行排序。

其實Zset在我們應用系統中能用到地方到處都是,這里我們舉一個簡單的例子,在團購系統中我們通常需要根據參團人數來排序成團列表,大家都希望參加那些即將成團的團。

下圖是一個根據團購code創建的Zset,score分值就是參團人數累加和:

Redis的數據類型及特點有哪些

ZADD zset:marketing:groupon:group:codes 5 G_PXYJY9QQFA 8 G_4EXMT6NZJQ 20 G_W7BMF5QC2P 10 G_429DHBTGZX 8 G_KHZGH9U4PP  ZREVRANGEBYSCORE zset:marketing:groupon:group:codes 1000 0  1) "G_W7BMF5QC2P"  2) "G_ZMZ69HJUCB"  3) "G_429DHBTGZX"  4) "G_KHZGH9U4PP"  5) "G_4EXMT6NZJQ"  6) "G_PXYJY9QQFA"    ZREVRANGEBYSCORE zset:marketing:groupon:group:codes 1000 0 withscores   1) "G_W7BMF5QC2P"   2) "20"   3) "G_ZMZ69HJUCB"   4) "10"  5) "G_429DHBTGZX"   6) "10"   7) "G_KHZGH9U4PP"   8) "8"   9) "G_4EXMT6NZJQ"  10) "8"  11) "G_PXYJY9QQFA"  12) "5"

Zset本身提供了很多方法用來進行集合的排序,如果需要score分值,可以使用withscore字句帶出每一項的分值。

在一些比較特殊的場合可能需要組合排序,可能有多個Zset分別用來對同一個實體在不同維度的排序,按時間排序、按人數排序等。這個時候就可以組合使用Zset帶來的便捷性,利用pipeline再結合多個Zset最終得出組合排序集合。

二、案例:滬江團購系統大促hot-top接口cache設計

以滬江團購系統大促hot-top接口cache設計為例,我們總結了Redis提供的5種數據類型的各自特點和一般的使用場景。但是我們不僅僅可以分開使用這些數據類型,我們完全可以綜合使用這些數據類型來完成復雜的cache場景。

下面我們分享一個使用多個Zset、String來優化團購系統前臺接口的例子。由于篇幅和時間限制,這里只介紹跟本次案例相關的信息。

注:hot-top接口是指熱點、排名接口的意思,表示它的瀏覽量、并發量比較高,一般大促的時候都會有幾個這種性能要求比較高的接口。

我們先來分析一個查詢接口所包含的常規信息。

首先一個查詢接口肯定是有query  condition查詢條件,然后是sort排序信息、***是page分頁信息。這是一般接口所承擔的基本職責,當然,特殊場景下還需要支持master/slave  replication時關于數據session一致性的要求,需要提供跟蹤標記來回master查詢數據,這里就不展開了。

我們可以抽象出這幾個維度的信息:

  • querycondition:查詢條件,companyid =100,sellerid=1010101諸如此類。

  • sort:排序信息,一般是默認一個列排序,但是在復雜的場景下會有可能讓接口使用者定制排序字段,比如一些租戶信息列。

  • page:分頁信息,簡單理解就是數據記錄排完序之后的第幾行到第幾行。

由于這里我們純粹用Redis來提高cache能力,不涉及到有關于任何搜索的能力,所以這里忽略其他復雜查詢的情況。其實我們在復雜的地方使用了Elastcsearch來提高搜索能力。

上述我們分析總結出了一個查詢接口的基本信息,這里還有一個有關于高并發接口的設計原則,就是將hot-top接口和一般search接口分離開,因為只有分而治之才能分別根據特點選用不同的技術。

如果我們不分職責將所有的查詢場景封裝在一個接口里,那么在后面優化接口性能的時候基本就很麻煩了,有些場景是無法或者很難用cache來解決的,因為接口里耦合了各種場景邏輯,就算勉強能實現性能也不會高。

前面做這些鋪墊是為了能在介紹案例的時候達成一個基本的共識。現在我們來看下這個團購系統的hot-top接口的具體邏輯。

注:在大促的時候需要展現團購列表,這個接口的訪問量是非常大的,團購活動需要根據參團人數倒序排序,并且分頁返回指定數量的團列表。我們假設這個接口名為getTopGroups(getTopGroupsRequestrequest)。

1)query condition查詢條件問題

我們來仔細分析下,首先不同的查詢條件從DB里查詢出來的數據是不一樣的,也就是說查詢出來的團列表是不一樣的,可能有company公司、channel渠道等過濾條件。

由于一個團購活動下不會有太多團,頂多上百個是極限了,所以一個查詢條件出來的團列表也頂多幾十個,而且根據場景分析熱點查詢條件不會超過十個,所以我們選擇將查詢條件Hash出一個code來緩存本次查詢條件的全量團列表集合,但是這些結果集是沒有任何排序的。

2)sort排序問題

再看根據參團人數排序問題,我們立刻就可以想到使用Zset來處理團排序問題,因為只有一個排序維度,所以一個Zset就夠了。我們使用一個Zset來緩存所有團的參團人數集合,它是一個全量的團排序集合。

那么我們如何將用戶的查詢條件出來的團列表根據參團人數排序呢?剛好可以使用Zset的交集運算,直接計算出當前這個集合的Zset子集。

3)page分頁問題

通過對已經排序之后的團列表Zset使用Zrange來獲取出分頁集合。我們來看下完整的流程,如何處理查詢、排序、分頁的。

下圖從query condition計算Hash Code,然后通過DB查詢出當前條件全量團列表:

Redis的數據類型及特點有哪些

zset:marketing:groupon:hottop:available:groupkey表示全量團的參團人數,用一個Zset來緩存。接著將這兩個Zset計算交集,就可以得出當前查詢所需要的帶有參團人數的Zset,***在使用Zrevrange獲取分頁區間。

ZADD zset:marketing:groupon:hottop:condition:2986080 0 G4ZD5732YZQ 0 G5VW3YF42UC 0 GF773FEJ7CC 0 GFW8DUEND8S 0 GKPKKW8XEY9 0 GL324DGWMZM  (integer) 6  ZADD zset:marketing:groupon:hottop:available:group 5 GN7KQH36ZWK 10 GS7VB22AWD4 15 GF773FEJ7CC 17 G5VW3YF42UC 18 G4ZD5732YZQ 32 GTYJKCEJBRR 40 GKPKKW8XEY9 45 GL324DGWMZM 50 GFW8DUEND8S 60 GYTKY4ACWLT  (integer) 10  ZINTERSTORE zset:marketing:groupon:hottop:condition:interstore 2 zset:marketing:groupon:hottop:condition:2986080 zset:marketing:groupon:hottop:available:group  (integer) 6  ZRANGE zset:marketing:groupon:hottop:condition:interstore 0 -1 withscores  1) "GF773FEJ7CC"  2) "15"  3) "G5VW3YF42UC"  4) "17"  5) "G4ZD5732YZQ"  6) "18"  7) "GKPKKW8XEY9"  8) "40"  9) "GL324DGWMZM"  10) "45"  11) "GFW8DUEND8S"  12) "50"  ZREVRANGE zset:marketing:groupon:hottop:condition:interstore 2 4 withscores  1) "GKPKKW8XEY9"  2) "40"  3) "G4ZD5732YZQ"  4) "18"  5) "G5VW3YF42UC"  6) "17"

有了返回的團code集合之后就可以通過mget來批量獲取String類型的團詳情信息,這里就不貼出代碼了。

以上是“Redis的數據類型及特點有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注創新互聯行業資訊頻道!

本文題目:Redis的數據類型及特點有哪些
本文鏈接:http://m.kartarina.com/article48/pgoehp.html

成都網站建設公司_創新互聯,為您提供域名注冊做網站響應式網站、品牌網站建設、網站改版企業網站制作

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

搜索引擎優化
主站蜘蛛池模板: 亚洲AV无码一区二区三区在线| 亚洲综合一区无码精品| 激情无码亚洲一区二区三区| 一区二区无码免费视频网站| 日韩视频无码日韩视频又2021| 国精品无码一区二区三区左线| 中文字幕人成无码人妻| 无码视频一区二区三区| 国产AV无码专区亚洲AV男同| 男男AV纯肉无码免费播放无码| 久久久久无码精品| 人妻中文字幕AV无码专区| 无码精品久久久天天影视| 日韩人妻无码精品专区| 熟妇人妻无码中文字幕老熟妇| 性无码免费一区二区三区在线| 免费无码午夜福利片| 东京热一精品无码AV| 在线观看无码AV网址| 无码国产乱人伦偷精品视频 | 亚洲AV无码专区日韩| 精品日韩亚洲AV无码一区二区三区| 无码人妻久久一区二区三区蜜桃 | 无码人妻一区二区三区一| 成人av片无码免费天天看| 无码人妻精品一区二区三区9厂| 色AV永久无码影院AV| 手机永久无码国产AV毛片| 国产精品无码久久久久久| 中文字幕无码av激情不卡久久 | 国产成人无码AⅤ片在线观看| 免费无码AV片在线观看软件| 色窝窝无码一区二区三区| 亚洲AV无码一区二区二三区软件| 国产成人精品无码片区在线观看| 精品国产毛片一区二区无码| 免费无码一区二区三区蜜桃| 人妻系列AV无码专区| 中文无码vs无码人妻| 亚洲一区无码中文字幕| 国产50部艳色禁片无码|