Remote DIctionary Server(Redis) 是一個(gè)由Salvatore Sanfilippo寫的key-value存儲(chǔ)系統(tǒng)。Redis是一個(gè)開源的使用ANSI C語(yǔ)言編寫、遵守BSD協(xié)議、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫(kù),并提供多種語(yǔ)言的API。
Redis經(jīng)常被用于緩存、分布式鎖等場(chǎng)景,其值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(set) 和 有序集合(sorted set)等類型。
1. String
redis的String類型不是我們通常理解的字符串類型,它是二進(jìn)制安全的,也就是說(shuō)只要是二進(jìn)制數(shù)據(jù),均可以進(jìn)行存儲(chǔ),包括數(shù)字、圖片、序列化對(duì)象等。
1.1 常用操作
#設(shè)置key的值
SET key value
#獲取key中的值
GET key
#刪除指定的key
DEL key
#對(duì)key中的數(shù)據(jù)進(jìn)行+1操作
INCR key
#對(duì)key中的數(shù)據(jù)進(jìn)行-1操作
DECR key
#如果不存在key,則將將key的值設(shè)置為value
SETNX key value
1.2 常見應(yīng)用場(chǎng)景:
1.2.1 緩存
??redis在后端應(yīng)用中常被用來(lái)當(dāng)做緩存中間件,我們根據(jù)接口或方法的入?yún)⑸梢粋€(gè)唯一的key,并在第一次調(diào)用后將返回值寫入redis中,對(duì)于后續(xù)的調(diào)用,如果發(fā)現(xiàn)入?yún)⑵ヅ?,只需要直接從緩存中獲取并返回給調(diào)用者,以減低服務(wù)器壓力。如果你使用Spring構(gòu)建后端應(yīng)用,可使用Spring Cache,其可提供基于redis的緩存支持。
1.2.2 計(jì)數(shù)器
??得益于redis的單線程模型,其上的操作均是線程安全的。使用incr key命令,我們可以輕松構(gòu)建一個(gè)線程安全的計(jì)數(shù)器,用于在線人數(shù)統(tǒng)計(jì)、商品庫(kù)存等場(chǎng)景。
1.2.3 分布式session
??redis因其超高的吞吐量,以及支持海量數(shù)據(jù)的存儲(chǔ)(通過(guò)集群突破單機(jī)上限),其除了用于緩存數(shù)據(jù),亦可用于實(shí)現(xiàn)分布式session。通過(guò)將集群?jiǎn)螌?shí)例的session存入redis中,可實(shí)現(xiàn)集群中的session共享。
2. List
??有序列表,redis采用雙鏈表實(shí)現(xiàn)list,支持從左右端(頭尾)進(jìn)行插入和刪除數(shù)據(jù)。一個(gè)列表最多可以包含 2^32 - 1 個(gè)元素。
2.1 常用操作
#獲取下標(biāo)start_index(包含)到stop_index(包含)的元素
LRANGE key start_inex stop_index
#從左側(cè)(頭部)插入元素,支持多個(gè)
LPUSH key value1 [value2]...
#從右側(cè)(尾部)插入元素,支持多個(gè)
RPUSH key value1 [value2]...
#獲取指定key的列表長(zhǎng)度
LLEN key
#從左側(cè)(頭部)彈出一個(gè)元素,該操作會(huì)在列表中刪除該元素
LPOP key
#從右側(cè)(尾部)彈出一個(gè)元素,該操作會(huì)在列表中刪除該元素
RPOP key
blpop/brpop
2.2 常見應(yīng)用場(chǎng)景:
2.2.1 消息流
??在對(duì)數(shù)據(jù)持久化要求不高的場(chǎng)景,我們可以使用redis的List來(lái)實(shí)現(xiàn)消息流,例如聊天記錄,公眾號(hào)推送列表等。使用LRANGE命令,我們可以根據(jù)前端的消息偏移量來(lái)取出用戶未讀取的消息。
3. Set
??Redis 的Set是String 類型的無(wú)序集合。集合成員是唯一的,這就意味著集合中不能出現(xiàn)重復(fù)的數(shù)據(jù)。Redis 中集合是通過(guò)哈希表實(shí)現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是 O(1)。集合中最大的成員數(shù)為 2^32 - 1 (40多億)。
3.1 常用操作
#向集合添加一個(gè)或多個(gè)元素
SADD key member1 [member2]...
#移除集合中的一個(gè)或多個(gè)元素
SREM key member1 [member2]...
#返回集合中的所有元素
SMEMBER key
#判斷member元素是否是集合 key 的成員
SISMEMBER key member
#從集合中隨機(jī)返回一個(gè)元素,該操作會(huì)在集合中刪除該元素
SPOP key
#從集合中隨機(jī)返回一個(gè)或多個(gè)元素
SRANDMEMBER key [count]
#計(jì)算指定集合的差集
SDIFF key1 key2 [key3]...
#計(jì)算指定集合的差集,并將結(jié)果存到destKey
SDIFFSTORE destKey key1 key2 [key3]...
#計(jì)算交集
SINTER key1 key2 [key3]...
#計(jì)算交集,并將結(jié)果存到destKey
SINTERSTORE destKey key1 key2 [key3]...
#計(jì)算并集
SUNION key1 key2 [key3]...
#計(jì)算并集,并將結(jié)果存儲(chǔ)到destKey
SUNIONSTORE destKey key1 key2 [key3]...
3.2 常見應(yīng)用場(chǎng)景
??redis中Set提供了差集,并集和交集計(jì)算,利用集合運(yùn)算我們可以輕松地實(shí)現(xiàn)社交場(chǎng)景中的許多功能。
3.2.1 我關(guān)注的人也關(guān)注了他
??我們可以以用戶Id作為key,好友列表以Set數(shù)據(jù)類型作為value。遍歷當(dāng)前用戶的好友列表,通過(guò)SISMEMBER 命令判斷好友的好友列表是否也包含了指定的用戶,即可得到“我關(guān)注的人也關(guān)注了他”的列表。
3.2.2 共同好友
??如3.2.1構(gòu)造好友列表數(shù)據(jù),然后通過(guò)求交集操作,即可計(jì)算出當(dāng)前用戶與指定用戶的共同好友。
3.2.3 抽獎(jiǎng)
??以活動(dòng)ID作為key,利用Set數(shù)據(jù)類型組織參與用戶ID并作為value。使用SRANDMEMBER命令即可從集合中隨機(jī)取出中獎(jiǎng)的用戶。
4. Hash
??Redis hash是一個(gè) string 類型的 field 和 value 的映射表,hash 特別適合用于存儲(chǔ)對(duì)象,每個(gè) hash 可以存儲(chǔ) 2^32 - 1 鍵值對(duì)(40多億)。
4.1 常用操作
#對(duì)指定key的field設(shè)置值
HSET key field value
#如果key中不存在field,則對(duì)指定的field設(shè)置值;如果key不存在,也會(huì)創(chuàng)建key并設(shè)置field
HSETNX key field value
#獲取指定key中指定的field的值
HMGET key field1 [field2]...
#刪除指定的filed
HDEL key field1 [field2]...
#對(duì)指定的filed進(jìn)行加操作
HINCRBY key field increment
4.2 常見應(yīng)用場(chǎng)景
4.2.1 購(gòu)物車
??在電商應(yīng)用中,購(gòu)物車是最基礎(chǔ)的功能之一,我們使用redis可以輕松地實(shí)現(xiàn)一個(gè)購(gòu)物車功能。我們使用用戶ID作為key,商品ID作為field,商品數(shù)量作為value。使用HINCRBY命令可以輕松實(shí)現(xiàn)商品的加減操作。
5. Sorted set
??Redis有序集合與Set集合基本一致,不同在于有序集合為每個(gè)元素加上了一個(gè)double類型的分?jǐn)?shù)。Redis通過(guò)該分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序。有序集合的成員是唯一的,但分?jǐn)?shù)(score)是可以重復(fù)的。
5.1 常用操作
#為指定key添加元素并設(shè)置分?jǐn)?shù)
ZADD key score1 member1 [score2 member2]...
#移除key中的指定元素
ZREM key member1 [member2]...
#對(duì)指定key中的指定元素的分?jǐn)?shù)進(jìn)行加操作
ZINCRBY key increment member
#獲取指定key中指定元素的分?jǐn)?shù)值
ZSCORE key member
#獲取指定區(qū)間內(nèi),帶有分?jǐn)?shù)值(可選)的有序集合元素列表(元素索引位置按分值從小到大)
ZRANGE key start_index stop_index [WITHSCORES]
#獲取指定區(qū)間內(nèi),帶有分?jǐn)?shù)值(可選)的有序集合元素列表(元素索引位置按分值從大到?。?ZREVRANGE key start_index stop_index [WITHSCORES]
#計(jì)算給定的有序集合的并集,并存儲(chǔ)到dest_key中,注意:不同集合中的相同元素,分?jǐn)?shù)會(huì)進(jìn)行累加
ZUNIONSTORE dest_key numberkeys key1 [key2]...
#計(jì)算給定的有序集合的交集,并存儲(chǔ)到dest_key中,注意:不同集合中的相同元素,分?jǐn)?shù)會(huì)進(jìn)行累加
ZINTERSTORE dest_key numberkeys key1 [key2]...
5.2 常見應(yīng)用場(chǎng)景
5.2.1 近7天熱搜
??由于有序集合中元素帶有分?jǐn)?shù),我們可以使用有序集合輕松實(shí)現(xiàn)每日排行榜。對(duì)于近7天熱搜榜,我們?cè)诿咳张判邪竦幕A(chǔ)上,再進(jìn)行并集操作即可實(shí)現(xiàn)。