這篇文章主要介紹“redis常用數(shù)據(jù)結(jié)構(gòu)有哪些及怎么實(shí)現(xiàn)”,在日常操作中,相信很多人在Redis常用數(shù)據(jù)結(jié)構(gòu)有哪些及怎么實(shí)現(xiàn)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Redis常用數(shù)據(jù)結(jié)構(gòu)有哪些及怎么實(shí)現(xiàn)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
為紅塔等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及紅塔網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、紅塔網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
Redis提供了一些數(shù)據(jù)結(jié)構(gòu)供我們往Redis中存取數(shù)據(jù),最常用的的有5種,字符串(String)、哈希(Hash)、列表(list)、集合(set)、有序集合(ZSET)。
字符串類型是Redis最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)。首先鍵都是字符串類型,而且其他幾種數(shù)據(jù)結(jié)構(gòu)都是在字符串類型基礎(chǔ)上構(gòu)建的,所以字符串類型能為其他四種數(shù)據(jù)結(jié)構(gòu)的學(xué)習(xí)奠定基礎(chǔ)。字符串類型的值實(shí)際可以是字符串(簡單的字符串、復(fù)雜的字符串(例如JSON、XML))、數(shù)字(整數(shù)、浮點(diǎn)數(shù)),甚至是二進(jìn)制(圖片、音頻、視頻),但是值最大不能超過512MB。
(雖然Redis是C寫的,C里面有字符串<本質(zhì)使用char數(shù)組來實(shí)現(xiàn)>,但是處于種種考慮,Redis還是自己實(shí)現(xiàn)了字符串類型)
set key value
set命令有幾個(gè)選項(xiàng):
ex seconds: 為鍵設(shè)置秒級過期時(shí)間。
px milliseconds: 為鍵設(shè)置毫秒級過期時(shí)間。
nx: 鍵必須不存在,才可以設(shè)置成功,用于添加(分布式鎖常用)。
xx: 與nx相反,鍵必須存在,才可以設(shè)置成功,用于更新。
從執(zhí)行效果上看,ex參數(shù)和expire命令基本一樣。還有一個(gè)需要特別注意的地方是如果一個(gè)字符串已經(jīng)設(shè)置了過期時(shí)間,然后你調(diào)用了set 方法修改了它,它的過期時(shí)間會消失。
而nx和xx執(zhí)行效果如下
除了set選項(xiàng),Redis 還提供了setex和 setnx兩個(gè)命令:
setex key seconds value
setnx key value
setex和 setnx的作用和ex和nx選項(xiàng)是一樣的。也就是,setex為鍵設(shè)置秒級過期時(shí)間,setnx設(shè)置時(shí)鍵必須不存在,才可以設(shè)置成功。
setex示例:
setnx示例:
因?yàn)殒Ifoo-ex已存在,所以setnx失敗,返回結(jié)果為0,鍵foo-ex2不存在,所以setnx成功,返回結(jié)果為1。
有什么應(yīng)用場景嗎?以setnx命令為例子,由于Redis的單線程命令處理機(jī)制,如果有多個(gè)客戶端同時(shí)執(zhí)行setnx key value,根據(jù)setnx的特性只有一個(gè)客戶端能設(shè)置成功,setnx可以作為分布式鎖的一種實(shí)現(xiàn)方案。當(dāng)然分布式鎖沒有不是只有一個(gè)命令就OK了,其中還有很多的東西要注意,我們后面會用單獨(dú)的章節(jié)來講述基于Redis的分布式鎖。
如果要獲取的鍵不存在,則返回nil(空):
通過mset命令一次性設(shè)置4個(gè)鍵值對
批量獲取了鍵a、b、c、d的值:
如果有些鍵不存在,那么它的值為nil(空),結(jié)果是按照傳入鍵的順序返回。
批量操作命令可以有效提高效率,假如沒有mget這樣的命令,要執(zhí)行n次get命令具體耗時(shí)如下:
n次 get時(shí)間=n次網(wǎng)絡(luò)時(shí)間+n次命令時(shí)間
使用mget命令后,要執(zhí)行n次get命令操作具體耗時(shí)如下:
n次get時(shí)間=1次網(wǎng)絡(luò)時(shí)間+n次命令時(shí)間
Redis可以支撐每秒數(shù)萬的讀寫操作,但是這指的是Redis服務(wù)端的處理能力,對于客戶端來說,一次命令除了命令時(shí)間還是有網(wǎng)絡(luò)時(shí)間,假設(shè)網(wǎng)絡(luò)時(shí)間為1毫秒,命令時(shí)間為0.1毫秒(按照每秒處理1萬條命令算),那么執(zhí)行1000次 get命令需要1.1秒(10001+10000.1=1100ms),1次mget命令的需要0.101秒(11+10000.1=101ms)。
incr命令用于對值做自增操作,返回結(jié)果分為三種情況:
值不是整數(shù),返回錯(cuò)誤。
值是整數(shù),返回自增后的結(jié)果。
鍵不存在,按照值為0自增,返回結(jié)果為1。
除了incr命令,Redis提供了decr(自減)、 incrby(自增指定數(shù)字)、decrby(自減指定數(shù)字)、incrbyfloat(自增浮點(diǎn)數(shù)),具體效果請同學(xué)們自行嘗試。
append可以向字符串尾部追加值
返回字符串長度
注意:每個(gè)中文占3個(gè)字節(jié)
getset和set一樣會設(shè)置值,但是不同的是,它同時(shí)會返回鍵原來的值
下標(biāo)從0開始計(jì)算。
getrange 截取字符串中的一部分,形成一個(gè)子串,需要指明開始和結(jié)束的偏移量,截取的范圍是個(gè)閉區(qū)間。
字符串這些命令中,除了del 、mset、 mget支持多個(gè)鍵的批量操作,時(shí)間復(fù)雜度和鍵的個(gè)數(shù)相關(guān),為O(n),getrange和字符串長度相關(guān),也是O(n),其余的命令基本上都是O(1)的時(shí)間復(fù)雜度,在速度上還是非??斓?。
字符串類型的使用場景很廣泛:
緩存功能
Redis 作為緩存層,MySQL作為存儲層,絕大部分請求的數(shù)據(jù)都是從Redis中獲取。由于Redis具有支撐高并發(fā)的特性,所以緩存通常能起到加速讀寫和降低后端壓力的作用。
計(jì)數(shù)
使用Redis 作為計(jì)數(shù)的基礎(chǔ)工具,它可以實(shí)現(xiàn)快速計(jì)數(shù)、查詢緩存的功能,同時(shí)數(shù)據(jù)可以異步落地到其他數(shù)據(jù)源。
共享Session
一個(gè)分布式Web服務(wù)將用戶的Session信息(例如用戶登錄信息)保存在各自服務(wù)器中,這樣會造成一個(gè)問題,出于負(fù)載均衡的考慮,分布式服務(wù)會將用戶的訪問均衡到不同服務(wù)器上,用戶刷新一次訪問可能會發(fā)現(xiàn)需要重新登錄,這個(gè)問題是用戶無法容忍的。
為了解決這個(gè)問題,可以使用Redis將用戶的Session進(jìn)行集中管理,,在這種模式下只要保證Redis是高可用和擴(kuò)展性的,每次用戶更新或者查詢登錄信息都直接從Redis中集中獲取。
限速
比如,很多應(yīng)用出于安全的考慮,會在每次進(jìn)行登錄時(shí),讓用戶輸入手機(jī)驗(yàn)證碼,從而確定是否是用戶本人。但是為了短信接口不被頻繁訪問,會限制用戶每分鐘獲取驗(yàn)證碼的頻率,例如一分鐘不能超過5次。一些網(wǎng)站限制一個(gè)IP地址不能在一秒鐘之內(nèi)方問超過n次也可以采用類似的思路。
Java里提供了HashMap,Redis中也有類似的數(shù)據(jù)結(jié)構(gòu),就是哈希類型。但是要注意,哈希類型中的映射關(guān)系叫作field-value,注意這里的value是指field對應(yīng)的值,不是鍵對應(yīng)的值。
基本上,哈希的操作命令和字符串的操作命令很類似,很多命令在字符串類型的命令前面加上了h字母,代表是操作哈希類型,同時(shí)還要指明要操作的field的值。
hset user:1 name lijin
如果設(shè)置成功會返回1,反之會返回0。此外Redis提供了hsetnx命令,它們的關(guān)系就像set和setnx命令一樣,只不過作用域由鍵變?yōu)閒ield。
hget user:1 name
如果鍵或field不存在,會返回nil。
hdel會刪除一個(gè)或多個(gè)field,返回結(jié)果為成功刪除field的個(gè)數(shù)。
若存在返回1,不存在返回0
它返回指定哈希鍵所有的field
在使用hgetall時(shí),如果哈希元素個(gè)數(shù)比較多,會存在阻塞Redis的可能。如果只需要獲取部分field,可以使用hmget,如果一定要獲取全部field-value,可以使用hscan命令,該命令會漸進(jìn)式遍歷哈希類型,hscan將在后面的章節(jié)介紹。
hincrby和 hincrbyfloat,就像incrby和incrbyfloat命令一樣,但是它們的作用域是filed。
哈希類型的操作命令中,hdel,hmget,hmset的時(shí)間復(fù)雜度和命令所帶的field的個(gè)數(shù)相關(guān)O(k),hkeys,hgetall,hvals和存儲的field的總數(shù)相關(guān),O(N)。其余的命令時(shí)間復(fù)雜度都是O(1)。
從前面的操作可以看出,String和Hash的操作非常類似,那為什么要弄一個(gè)hash出來存儲。
哈希類型比較適宜存放對象類型的數(shù)據(jù),我們可以比較下,如果數(shù)據(jù)庫中表記錄user為:
id | name | age |
---|---|---|
1 | lijin | 18 |
2 | msb | 20 |
1、使用String類型
需要一條條去插入獲取。
set user:1:name lijin;
set user:1:age 18;
set user:2:name msb;
set user:2:age 20;
優(yōu)點(diǎn):簡單直觀,每個(gè)鍵對應(yīng)一個(gè)值
缺點(diǎn):鍵數(shù)過多,占用內(nèi)存多,用戶信息過于分散,不用于生產(chǎn)環(huán)境
2、將對象序列化存入redis
set user:1 serialize(userInfo);
優(yōu)點(diǎn):編程簡單,若使用序列化合理內(nèi)存使用率高
缺點(diǎn):序列化與反序列化有一定開銷,更新屬性時(shí)需要把userInfo全取出來進(jìn)行反序列化,更新后再序列化到redis
3、使用hash類型
hmset user:1 name lijin age 18
hmset user:2 name msb age 20
優(yōu)點(diǎn):簡單直觀,使用合理可減少內(nèi)存空間消耗
缺點(diǎn):要控制內(nèi)部編碼格式,不恰當(dāng)?shù)母袷綍母鄡?nèi)存
列表( list)類型是用來存儲多個(gè)有序的字符串,a、b、c、c、b四個(gè)元素從左到右組成了一個(gè)有序的列表,列表中的每個(gè)字符串稱為元素(element),一個(gè)列表最多可以存儲(2^32-1)個(gè)元素(4294967295)。
在Redis 中,可以對列表兩端插入( push)和彈出(pop),還可以獲取指定范圍的元素列表、獲取指定索引下標(biāo)的元素等。列表是一種比較靈活的數(shù)據(jù)結(jié)構(gòu),它可以充當(dāng)棧和隊(duì)列的角色,在實(shí)際開發(fā)上有很多應(yīng)用場景。
列表類型有兩個(gè)特點(diǎn):
第一、列表中的元素是有序的,這就意味著可以通過索引下標(biāo)獲取某個(gè)元素或者某個(gè)范圍內(nèi)的元素列表。
第二、列表中的元素可以是重復(fù)的。
key start end
索引下標(biāo)特點(diǎn):從左到右為0到N-1
lrange 0 -1命令可以從左到右獲取列表的所有元素
這三個(gè)返回結(jié)果為命令完成后當(dāng)前列表的長度,也就是列表中包含的元素個(gè)數(shù),同時(shí)rpush和lpush都支持同時(shí)插入多個(gè)元素。
r
請注意,彈出來元素就沒了。
rpop將會把列表最右側(cè)的元素d彈出。
lrem命令會從列表中找到等于value的元素進(jìn)行刪除,根據(jù)count的不同分為三種情況:
count>0,從左到右,刪除最多count個(gè)元素。
count<0,從右到左,刪除最多count絕對值個(gè)元素。
count=0,刪除所有。
返回值是實(shí)際刪除元素的個(gè)數(shù)。
例如想保留列表中第0個(gè)到第1個(gè)元素
ls
l
blpop和brpop是lpop和rpop的阻塞版本,除此之外還支持多個(gè)列表類型,也支持設(shè)定阻塞時(shí)間,單位秒,如果阻塞時(shí)間為0,表示一直阻塞下去。我們以brpop為例說明。
A客戶端阻塞了(因?yàn)闆]有元素就會阻塞)
A客戶端一直處于阻塞狀態(tài)。此時(shí)我們從另一個(gè)客戶端B執(zhí)行
A客戶端則輸出
注意:brpop后面如果是多個(gè)鍵,那么brpop會從左至右遍歷鍵,一旦有一個(gè)鍵能彈出元素,客戶端立即返回。
列表類型可以用于比如:
消息隊(duì)列,Redis 的 lpush+brpop命令組合即可實(shí)現(xiàn)阻塞隊(duì)列,生產(chǎn)者客戶端使用lrpush從列表左側(cè)插入元素,多個(gè)消費(fèi)者客戶端使用brpop命令阻塞式的“搶”列表尾部的元素,多個(gè)客戶端保證了消費(fèi)的負(fù)載均衡和高可用性。
文章列表
每個(gè)用戶有屬于自己的文章列表,現(xiàn)需要分頁展示文章列表。此時(shí)可以考慮使用列表,因?yàn)榱斜聿坏怯行虻?同時(shí)支持按照索引范圍獲取元素。
實(shí)現(xiàn)其他數(shù)據(jù)結(jié)構(gòu)
lpush+lpop =Stack(棧)
lpush +rpop =Queue(隊(duì)列)
lpsh+ ltrim =Capped Collection(有限集合)
lpush+brpop=Message Queue(消息隊(duì)列)
集合( set)類型也是用來保存多個(gè)的字符串元素,但和列表類型不一樣的是,集合中不允許有重復(fù)元素,并且集合中的元素是無序的,不能通過索引下標(biāo)獲取元素。
一個(gè)集合最多可以存儲2的32次方-1個(gè)元素。Redis除了支持集合內(nèi)的增刪改查,同時(shí)還支持多個(gè)集合取交集、并集、差集,合理地使用好集合類型,能在實(shí)際開發(fā)中解決很多實(shí)際問題。
允許添加多個(gè),返回結(jié)果為添加成功的元素個(gè)數(shù)
允許刪除多個(gè),返回結(jié)果為成功刪除元素個(gè)數(shù)
如果給定元素element在集合內(nèi)返回1,反之返回0
指定個(gè)數(shù)如果不寫默認(rèn)為1
同樣可以指定個(gè)數(shù),如果不寫默認(rèn)為1,注意,既然是彈出,spop命令執(zhí)行后,元素會從集合中刪除,而srandmember不會。
返回結(jié)果是無序的
現(xiàn)在有兩個(gè)集合,它們分別是set1和set2
sinterstore destination key [key ...] suionstore destination key [key ...] sdiffstore destination key [key ...]復(fù)制代碼
集合間的運(yùn)算在元素較多的情況下會比較耗時(shí),所以 Redis提供了上面三個(gè)命令(原命令+store)將集合間交集、并集、差集的結(jié)果保存在destination key中,例如:
集合類型比較典型的使用場景是標(biāo)簽(tag)。例如一個(gè)用戶可能對娛樂、體育比較感興趣,另一個(gè)用戶可能對歷史、新聞比較感興趣,這些興趣點(diǎn)就是標(biāo)簽。有了這些數(shù)據(jù)就可以得到喜歡同一個(gè)標(biāo)簽的人,以及用戶的共同喜好的標(biāo)簽,這些數(shù)據(jù)對于用戶體驗(yàn)以及增強(qiáng)用戶黏度比較重要。
例如一個(gè)電子商務(wù)的網(wǎng)站會對不同標(biāo)簽的用戶做不同類型的推薦,比如對數(shù)碼產(chǎn)品比較感興趣的人,在各個(gè)頁面或者通過郵件的形式給他們推薦最新的數(shù)碼產(chǎn)品,通常會為網(wǎng)站帶來更多的利益。
除此之外,集合還可以通過生成隨機(jī)數(shù)進(jìn)行比如抽獎(jiǎng)活動,以及社交圖譜等等。
有序集合相對于哈希、列表、集合來說會有一點(diǎn)點(diǎn)陌生,但既然叫有序集合,那么它和集合必然有著聯(lián)系,它保留了集合不能有重復(fù)成員的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下標(biāo)作為排序依據(jù)不同的是,它給每個(gè)元素設(shè)置一個(gè)分?jǐn)?shù)( score)作為排序的依據(jù)。
有序集合中的元素不能重復(fù),但是score可以重復(fù),就和一個(gè)班里的同學(xué)學(xué)號不能重復(fù),但是考試成績可以相同。
有序集合提供了獲取指定分?jǐn)?shù)和元素范圍查詢、計(jì)算成員排名等功能,合理的利用有序集合,能幫助我們在實(shí)際開發(fā)中解決很多問題。
返回結(jié)果代表成功添加成員的個(gè)數(shù)
要注意:
zadd命令還有四個(gè)選項(xiàng)nx、xx、ch、incr 四個(gè)選項(xiàng)
nx: member必須不存在,才可以設(shè)置成功,用于添加。
xx: member必須存在,才可以設(shè)置成功,用于更新。
ch: 返回此次操作后,有序集合元素和分?jǐn)?shù)發(fā)生變化的個(gè)數(shù)
incr: 對score做增加,相當(dāng)于后面介紹的zincrby
如果成員不存在則返回nil
zrank是從分?jǐn)?shù)從低到高返回排名
zrevrank反之
很明顯,排名從0開始計(jì)算。
允許一次刪除多個(gè)成員。
返回結(jié)果為成功刪除的個(gè)數(shù)。
有序集合是按照分值排名的,zrange是從低到高返回,zrevrange反之。如果加上 withscores選項(xiàng),同時(shí)會返回成員的分?jǐn)?shù)
zrangebyscore key min max [withscores] [limit offset count] zrevrangebyscore key max min [withscores][limit offset count]復(fù)制代碼
其中zrangebyscore按照分?jǐn)?shù)從低到高返回,zrevrangebyscore反之。例如下面操作從低到高返回200到221分的成員,withscores選項(xiàng)會同時(shí)返回每個(gè)成員的分?jǐn)?shù)。
同時(shí)min和max還支持開區(qū)間(小括號)和閉區(qū)間(中括號),-inf和+inf分別代表無限小和無限大:
zcount key min max
zremrangebyrank key start end
zremrangebyscore key min max
zinterstore
這個(gè)命令參數(shù)較多,下面分別進(jìn)行說明
destination:交集計(jì)算結(jié)果保存到這個(gè)鍵。
numkeys:需要做交集計(jì)算鍵的個(gè)數(shù)。
key [key ...]:需要做交集計(jì)算的鍵。
weights weight [weight ...]:每個(gè)鍵的權(quán)重,在做交集計(jì)算時(shí),每個(gè)鍵中的每個(gè)member 會將自己分?jǐn)?shù)乘以這個(gè)權(quán)重,每個(gè)鍵的權(quán)重默認(rèn)是1。
aggregate sum/ min |max:計(jì)算成員交集后,分值可以按照sum(和)、min(最小值)、max(最大值)做匯總,默認(rèn)值是sum。
不太好理解,我們用一個(gè)例子來說明。(算平均分)
該命令的所有參數(shù)和zinterstore是一致的,只不過是做并集計(jì)算,大家可以自行實(shí)驗(yàn)。
到此,關(guān)于“Redis常用數(shù)據(jù)結(jié)構(gòu)有哪些及怎么實(shí)現(xiàn)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
分享題目:Redis常用數(shù)據(jù)結(jié)構(gòu)有哪些及怎么實(shí)現(xiàn)
鏈接地址:http://www.rwnh.cn/article26/jishjg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、網(wǎng)站維護(hù)、網(wǎng)站內(nèi)鏈、品牌網(wǎng)站制作、云服務(wù)器、營銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)