共計(jì) 7603 個(gè)字符,預(yù)計(jì)需要花費(fèi) 20 分鐘才能閱讀完成。
這篇文章主要介紹“Redis 的優(yōu)勢(shì)和特點(diǎn)有哪些”的相關(guān)知識(shí),丸趣 TV 小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“Redis 的優(yōu)勢(shì)和特點(diǎn)有哪些”文章能幫助大家解決問(wèn)題。
什么是 redis
Remote DIctionary Server(Redis) 是一個(gè)由 Salvatore Sanfilippo 寫的 key-value 存儲(chǔ)系統(tǒng),是跨平臺(tái)的非關(guān)系型數(shù)據(jù)庫(kù)。
Redis 是一個(gè)開源的使用 ANSI C 語(yǔ)言編寫、遵守 BSD 協(xié)議、支持網(wǎng)絡(luò)、可基于內(nèi)存、分布式、可選持久性的鍵值對(duì) (Key-Value) 存儲(chǔ)數(shù)據(jù)庫(kù),并提供多種語(yǔ)言的 API。
Redis 通常被稱為數(shù)據(jù)結(jié)構(gòu)服務(wù)器,因?yàn)橹担╲alue)可以是字符串 (String)、哈希(Hash)、列表(list)、集合(sets) 和有序集合 (sorted sets) 等類型。
Redis 的特點(diǎn):
內(nèi)存數(shù)據(jù)庫(kù),速度快,也支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時(shí)候可以再次加載進(jìn)行使用。
Redis 不僅僅支持簡(jiǎn)單的 key-value 類型的數(shù)據(jù),同時(shí)還提供 list,set,zset,hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
Redis 支持?jǐn)?shù)據(jù)的備份,即 master-slave 模式的數(shù)據(jù)備份。
支持事務(wù)
Redis 的優(yōu)勢(shì):
性能極高 – Redis 能讀的速度是 110000 次 /s, 寫的速度是 81000 次 /s。
豐富的數(shù)據(jù)類型 – Redis 支持二進(jìn)制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作。
原子 – Redis 的所有操作都是原子性的,同時(shí) Redis 還支持對(duì)幾個(gè)操作合并后的原子性執(zhí)行。(事務(wù))
豐富的特性 – Redis 還支持 publish/subscribe, 通知, key 過(guò)期等等特性。
Redis 與其他 key-value 存儲(chǔ)有什么不同?
Redis 有著更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)并且提供對(duì)他們的原子性操作,這是一個(gè)不同于其他數(shù)據(jù)庫(kù)的進(jìn)化路徑。Redis 的數(shù)據(jù)類型都是基于基本數(shù)據(jù)結(jié)構(gòu)的同時(shí)對(duì)程序員透明,無(wú)需進(jìn)行額外的抽象。
Redis 運(yùn)行在內(nèi)存中但是可以持久化到磁盤,所以在對(duì)不同數(shù)據(jù)集進(jìn)行高速讀寫時(shí)需要權(quán)衡內(nèi)存,因?yàn)閿?shù)據(jù)量不能大于硬件內(nèi)存。在內(nèi)存數(shù)據(jù)庫(kù)方面的另一個(gè)優(yōu)點(diǎn)是,相比在磁盤上相同的復(fù)雜的數(shù)據(jù)結(jié)構(gòu),在內(nèi)存中操作起來(lái)非常簡(jiǎn)單,這樣 Redis 可以做很多內(nèi)部復(fù)雜性很強(qiáng)的事情。同時(shí),在磁盤格式方面他們是緊湊的以追加的方式產(chǎn)生的,因?yàn)樗麄儾⒉恍枰M(jìn)行隨機(jī)訪問(wèn)。
Memcache 與 Redis 的區(qū)別都有哪些
存儲(chǔ)方式 Memecache 把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會(huì)掛掉,數(shù)據(jù)不能超過(guò)內(nèi)存大小。Redis 有部份存在硬盤上,redis 可以持久化其數(shù)據(jù)
數(shù)據(jù)支持類型 memcached 所有的值均是簡(jiǎn)單的字符串,redis 作為其替代者,支持更為豐富的數(shù)據(jù)類型,提供 list,set,zset,hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)
使用底層模型不同 它們之間底層實(shí)現(xiàn)方式 以及與客戶端之間通信的應(yīng)用協(xié)議不一樣。Redis 直接自己構(gòu)建了 VM 機(jī)制,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會(huì)浪費(fèi)一定的時(shí)間去移動(dòng)和請(qǐng)求。
value 值大小不同:Redis 最大可以達(dá)到 512M;memcache 只有 1mb。
redis 的速度比 memcached 快很多
Redis 支持?jǐn)?shù)據(jù)的備份,即 master-slave 模式的數(shù)據(jù)備份。
Redis 為什么這么快
1、完全基于內(nèi)存,絕大部分請(qǐng)求是純粹的內(nèi)存操作,非??焖佟?shù)據(jù)存在內(nèi)存中,類似于 HashMap,HashMap 的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是 O(1);
2、數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,對(duì)數(shù)據(jù)操作也簡(jiǎn)單,Redis 中的數(shù)據(jù)結(jié)構(gòu)是專門進(jìn)行設(shè)計(jì)的;
3、采用單線程,避免了不必要的上下文切換和競(jìng)爭(zhēng)條件,也不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗 CPU,不用去考慮各種鎖的問(wèn)題,不存在加鎖釋放鎖操作,沒(méi)有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能消耗;
4、使用多路 I / O 復(fù)用模型,非阻塞 IO;
5、使用底層模型不同,它們之間底層實(shí)現(xiàn)方式以及與客戶端之間通信的應(yīng)用協(xié)議不一樣,Redis 直接自己構(gòu)建了 VM 機(jī)制,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會(huì)浪費(fèi)一定的時(shí)間去移動(dòng)和請(qǐng)求;
6. 多路 I/O 復(fù)用模型
多路 I / O 復(fù)用模型是利用 select、poll、epoll 可以同時(shí)監(jiān)察多個(gè)流的 I/O 事件的能力,在空閑的時(shí)候,會(huì)把當(dāng)前線程阻塞掉,當(dāng)有一個(gè)或多個(gè)流有 I/O 事件時(shí),就從阻塞態(tài)中喚醒,于是程序就會(huì)輪詢一遍所有的流(epoll 是只輪詢那些真正發(fā)出了事件的流),并且只依次順序的處理就緒的流,這種做法就避免了大量的無(wú)用操作。
** 這里“多路”指的是多個(gè)網(wǎng)絡(luò)連接,“復(fù)用”指的是復(fù)用同一個(gè)線程。** 采用多路 I/O 復(fù)用技術(shù)可以讓單個(gè)線程高效的處理多個(gè)連接請(qǐng)求(盡量減少網(wǎng)絡(luò) IO 的時(shí)間消耗),且 Redis 在內(nèi)存中操作數(shù)據(jù)的速度非常快,也就是說(shuō)內(nèi)存內(nèi)的操作不會(huì)成為影響 Redis 性能的瓶頸,主要由以上幾點(diǎn)造就了 Redis 具有很高的吞吐量。
那么為什么 Redis 是單線程的
我們首先要明白,上邊的種種分析,都是為了營(yíng)造一個(gè) Redis 很快的氛圍!官方 FAQ 表示,因?yàn)?Redis 是基于內(nèi)存的操作,CPU 不是 Redis 的瓶頸,Redis 的瓶頸最有可能是機(jī)器內(nèi)存的大小或者網(wǎng)絡(luò)帶寬。既然單線程容易實(shí)現(xiàn),而且 CPU 不會(huì)成為瓶頸,那就順理成章地采用單線程的方案了(畢竟采用多線程會(huì)有很多麻煩!)。
Redis 數(shù)據(jù)類型及命令
1. 字符串(String)
redis 127.0.0.1:6379 SET rediskey redis
redis 127.0.0.1:6379 GET rediskey
redis
2. 哈希(Hash)
Redis hash 是一個(gè) string 類型的 field(字段)和 value(值)的映射表,hash 特別適合用于存儲(chǔ)對(duì)象。
Redis 中每個(gè) hash 可以存儲(chǔ) 232 – 1 鍵值對(duì)(40 多億)
3. 列表(List)
Redis 列表是簡(jiǎn)單的字符串列表,按照插入順序排序。你可以添加一個(gè)元素到列表的頭部(左邊)或者尾部(右邊)
一個(gè)列表最多可以包含 232 – 1 個(gè)元素 (4294967295, 每個(gè)列表超過(guò) 40 億個(gè)元素)。
redis 127.0.0.1:6379 LPUSH rediskey redis
(integer) 1
redis 127.0.0.1:6379 LPUSH rediskey mongodb
(integer) 2
redis 127.0.0.1:6379 LPUSH rediskey mysql
(integer) 3
redis 127.0.0.1:6379 LRANGE rediskey 0 10
1) mysql
2) mongodb
3) redis
4. 集合(Set)
Redis 的 Set 是 String 類型的無(wú)序集合。集合成員是唯一的,這就意味著集合中不能出現(xiàn)重復(fù)的數(shù)據(jù)。
集合對(duì)象的編碼可以是 intset 或者 hashtable。
Redis 中集合是通過(guò)哈希表實(shí)現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是 O(1)。
集合中最大的成員數(shù)為 232 – 1 (4294967295, 每個(gè)集合可存儲(chǔ) 40 多億個(gè)成員)。
redis 127.0.0.1:6379 SADD rediskey redis
(integer) 1
redis 127.0.0.1:6379 SADD rediskey mongodb
(integer) 1
redis 127.0.0.1:6379 SADD rediskey mysql
(integer) 1
redis 127.0.0.1:6379 SADD rediskey mysql
(integer) 0
redis 127.0.0.1:6379 SMEMBERS rediskey
1) mysql
2) mongodb
3) redis
5. 有序集合(sorted set)
Redis 有序集合和集合一樣也是 string 類型元素的集合, 且不允許重復(fù)的成員。
不同的是每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè) double 類型的分?jǐn)?shù)。redis 正是通過(guò)分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序。
有序集合的成員是唯一的, 但分?jǐn)?shù) (score) 卻可以重復(fù)。
集合是通過(guò)哈希表實(shí)現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是 O(1)。集合中最大的成員數(shù)為 232 – 1 (4294967295, 每個(gè)集合可存儲(chǔ) 40 多億個(gè)成員)。
6. HyperLogLog
Redis 在 2.8.9 版本添加了 HyperLogLog 結(jié)構(gòu)。
Redis HyperLogLog 是用來(lái)做基數(shù)統(tǒng)計(jì)的算法,HyperLogLog 的優(yōu)點(diǎn)是,在輸入元素的數(shù)量或者體積非常非常大時(shí),計(jì)算基數(shù)所需的空間總是固定 的、并且是很小的。
在 Redis 里面,每個(gè) HyperLogLog 鍵只需要花費(fèi) 12 KB 內(nèi)存,就可以計(jì)算接近 2^64 個(gè)不同元素的基 數(shù)。這和計(jì)算基數(shù)時(shí),元素越多耗費(fèi)內(nèi)存就越多的集合形成鮮明對(duì)比。
但是,因?yàn)?HyperLogLog 只會(huì)根據(jù)輸入元素來(lái)計(jì)算基數(shù),而不會(huì)儲(chǔ)存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個(gè)元素。
什么是基數(shù)?
比如數(shù)據(jù)集 {1, 3, 5, 7, 5, 7, 8},那么這個(gè)數(shù)據(jù)集的基數(shù)集為 {1, 3, 5 ,7, 8}, 基數(shù) (不重復(fù)元素) 為 5?;鶖?shù)估計(jì)就是在誤差可接受的范圍內(nèi),快速計(jì)算基數(shù)。
實(shí)例
以下實(shí)例演示了 HyperLogLog 的工作過(guò)程:
// 添加指定元素到 HyperLogLog 中。redis 127.0.0.1:6379 PFADD rediskey redis
1) (integer) 1
redis 127.0.0.1:6379 PFADD rediskey mongodb
1) (integer) 1
redis 127.0.0.1:6379 PFADD rediskey mysql
1) (integer) 1
// 添加指定元素到 HyperLogLog 中。redis 127.0.0.1:6379 PFCOUNT rediskey
(integer) 3
7. 發(fā)布訂閱
Redis 發(fā)布訂閱 (pub/sub) 是一種消息通信模式:發(fā)送者 (pub) 發(fā)送消息,訂閱者 (sub) 接收消息。
Redis 客戶端可以訂閱任意數(shù)量的頻道。
下圖展示了頻道 channel1,以及訂閱這個(gè)頻道的三個(gè)客戶端 —— client2、client5 和 client1 之間的關(guān)系:
實(shí)例
以下實(shí)例演示了發(fā)布訂閱是如何工作的,需要開啟兩個(gè) redis-cli 客戶端。
在我們實(shí)例中我們創(chuàng)建了訂閱頻道名為 runoobChat:
第一個(gè) redis-cli 客戶端
redis 127.0.0.1:6379 SUBSCRIBE runoobChat
Reading messages... (press Ctrl-C to quit)
1) subscribe
2) runoobChat
3) (integer) 1
現(xiàn)在,我們先重新開啟個(gè) redis 客戶端,然后在同一個(gè)頻道 runoobChat 發(fā)布兩次消息,訂閱者就能接收到消息。
第二個(gè) redis-cli 客戶端
redis 127.0.0.1:6379 PUBLISH runoobChat Redis PUBLISH test
(integer) 1
redis 127.0.0.1:6379 PUBLISH runoobChat Learn redis by runoob.com
(integer) 1
# 訂閱者的客戶端會(huì)顯示如下消息
1) message
2) runoobChat
3) Redis PUBLISH test
1) message
2) runoobChat
3) Learn redis by runoob.com
gif 演示如下:
開啟本地 Redis 服務(wù),開啟兩個(gè) redis-cli 客戶端。
在第一個(gè) redis-cli 客戶端輸入 SUBSCRIBE runoobChat,意思是訂閱 runoobChat 頻道。
在第二個(gè) redis-cli 客戶端輸入 PUBLISH runoobChat“Redis PUBLISH test”往 runoobChat 頻道發(fā)送消息,這個(gè)時(shí)候在第一個(gè) redis-cli 客戶端就會(huì)看到由第二個(gè) redis-cli 客戶端發(fā)送的測(cè)試消息。
8. 事務(wù)
Redis 事務(wù)可以一次執(zhí)行多個(gè)命令,并且?guī)в幸韵氯齻€(gè)重要的保證:
批量操作在發(fā)送 EXEC 命令前被放入隊(duì)列緩存。
收到 EXEC 命令后進(jìn)入事務(wù)執(zhí)行,事務(wù)中任意命令執(zhí)行失敗,其余的命令依然被執(zhí)行。
在事務(wù)執(zhí)行過(guò)程,其他客戶端提交的命令請(qǐng)求不會(huì)插入到事務(wù)執(zhí)行命令序列中。
一個(gè)事務(wù)從開始到執(zhí)行會(huì)經(jīng)歷以下三個(gè)階段:
開始事務(wù)。
命令入隊(duì)。
執(zhí)行事務(wù)。
實(shí)例
以下是一個(gè)事務(wù)的例子,它先以 MULTI 開始一個(gè)事務(wù),然后將多個(gè)命令入隊(duì)到事務(wù)中,最后由 EXEC 命令觸發(fā)事務(wù),一并執(zhí)行事務(wù)中的所有命令:
redis 127.0.0.1:6379 MULTI
redis 127.0.0.1:6379 SET book-name Mastering C++ in 21 days
QUEUED
redis 127.0.0.1:6379 GET book-name
QUEUED
redis 127.0.0.1:6379 SADD tag C++ Programming Mastering Series
QUEUED
redis 127.0.0.1:6379 SMEMBERS tag
QUEUED
redis 127.0.0.1:6379 EXEC
1) OK
2) Mastering C++ in 21 days
3) (integer) 3
4) 1) Mastering Series
2) C++
3) Programming
單個(gè) Redis 命令的執(zhí)行是原子性的,但 Redis 沒(méi)有在事務(wù)上增加任何維持原子性的機(jī)制,所以 Redis 事務(wù)的執(zhí)行并不是原子性的。
事務(wù)可以理解為一個(gè)打包的批量執(zhí)行腳本,但批量指令并非原子化的操作,中間某條指令的失敗不會(huì)導(dǎo)致前面已做指令的回滾,也不會(huì)造成后續(xù)的指令不做。
這是官網(wǎng)上的說(shuō)明 From redis docs on transactions:
It’s important to note that even when a command fails, all the other commands in the queue are processed – Redis will not stop the processing of commands.
比如:
redis 127.0.0.1:7000 multi
redis 127.0.0.1:7000 set a aaa
QUEUED
redis 127.0.0.1:7000 set b bbb
QUEUED
redis 127.0.0.1:7000 set c ccc
QUEUED
redis 127.0.0.1:7000 exec
1) OK
2) OK
3) OK
如果在 set b bbb 處失敗,set a 已成功不會(huì)回滾,set c 還會(huì)繼續(xù)執(zhí)行。
9. 腳本
Redis 腳本使用 Lua 解釋器來(lái)執(zhí)行腳本。Redis 2.6 版本通過(guò)內(nèi)嵌支持 Lua 環(huán)境。執(zhí)行腳本的常用命令為 EVAL。
redis 127.0.0.1:6379 EVAL return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]} 2 key1 key2 first second
1) key1
2) key2
3) first
4) second
10 GEO
Redis GEO 主要用于存儲(chǔ)地理位置信息,并對(duì)存儲(chǔ)的信息進(jìn)行操作,該功能在 Redis 3.2 版本新增。
Redis GEO 操作方法有:
geoadd:添加地理位置的坐標(biāo)。
geopos:獲取地理位置的坐標(biāo)。
geodist:計(jì)算兩個(gè)位置之間的距離。
georadius:根據(jù)用戶給定的經(jīng)緯度坐標(biāo)來(lái)獲取指定范圍內(nèi)的地理位置集合。
georadiusbymember:根據(jù)儲(chǔ)存在位置集合里面的某個(gè)地點(diǎn)獲取指定范圍內(nèi)的地理位置集合。
geohash:返回一個(gè)或多個(gè)位置對(duì)象的 geohash 值。
redis GEOADD Sicily 13.361389 38.115556 Palermo 15.087269 37.502669 Catania
(integer) 2
redis GEODIST Sicily Palermo Catania
166274.1516
redis GEORADIUS Sicily 15 37 100 km
1) Catania
redis GEORADIUS Sicily 15 37 200 km
1) Palermo
2) Catania
redis
11 Redis Stream
Redis Stream 是 Redis 5.0 版本新增加的數(shù)據(jù)結(jié)構(gòu)。
Redis Stream 主要用于消息隊(duì)列(MQ,Message Queue),Redis 本身是有一個(gè) Redis 發(fā)布訂閱 (pub/sub) 來(lái)實(shí)現(xiàn)消息隊(duì)列的功能,但它有個(gè)缺點(diǎn)就是消息無(wú)法持久化,如果出現(xiàn)網(wǎng)絡(luò)斷開、Redis 宕機(jī)等,消息就會(huì)被丟棄。
簡(jiǎn)單來(lái)說(shuō)發(fā)布訂閱 (pub/sub) 可以分發(fā)消息,但無(wú)法記錄歷史消息。
而 Redis Stream 提供了消息的持久化和主備復(fù)制功能,可以讓任何客戶端訪問(wèn)任何時(shí)刻的數(shù)據(jù),并且能記住每一個(gè)客戶端的訪問(wèn)位置,還能保證消息不丟失。
Redis Stream 的結(jié)構(gòu)如下所示,它有一個(gè)消息鏈表,將所有加入的消息都串起來(lái),每個(gè)消息都有一個(gè)唯一的 ID 和對(duì)應(yīng)的內(nèi)容:
每個(gè) Stream 都有唯一的名稱,它就是 Redis 的 key,在我們首次使用 xadd 指令追加消息時(shí)自動(dòng)創(chuàng)建。
上圖解析:
Consumer Group:消費(fèi)組,使用 XGROUP CREATE 命令創(chuàng)建,一個(gè)消費(fèi)組有多個(gè)消費(fèi)者(Consumer)。
last_delivered_id:游標(biāo),每個(gè)消費(fèi)組會(huì)有個(gè)游標(biāo) last_delivered_id,任意一個(gè)消費(fèi)者讀取了消息都會(huì)使游標(biāo) last_delivered_id 往前移動(dòng)。
pending_ids:消費(fèi)者 (Consumer) 的狀態(tài)變量,作用是維護(hù)消費(fèi)者的未確認(rèn)的 id。pending_ids 記錄了當(dāng)前已經(jīng)被客戶端讀取的消息,但是還沒(méi)有 ack (Acknowledge character:確認(rèn)字符)。
Redis 管道技術(shù)
Redis 是一種基于客戶端 - 服務(wù)端模型以及請(qǐng)求 / 響應(yīng)協(xié)議的 TCP 服務(wù)。這意味著通常情況下一個(gè)請(qǐng)求會(huì)遵循以下步驟:
客戶端向服務(wù)端發(fā)送一個(gè)查詢請(qǐng)求,并監(jiān)聽 Socket 返回,通常是以阻塞模式,等待服務(wù)端響應(yīng)。
服務(wù)端處理命令,并將結(jié)果返回給客戶端。
Redis 管道技術(shù)
Redis 管道技術(shù)可以在服務(wù)端未響應(yīng)時(shí),客戶端可以繼續(xù)向服務(wù)端發(fā)送請(qǐng)求,并最終一次性讀取所有服務(wù)端的響應(yīng)。
關(guān)于“Redis 的優(yōu)勢(shì)和特點(diǎn)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注丸趣 TV 行業(yè)資訊頻道,丸趣 TV 小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。