這篇文章為大家帶來了關於Redis的相關知識,其中主要介紹了關於redis的一些優勢和特點,Redis 是一個開源的使用ANSI C語言編寫、遵守BSD 協議、支援網路、可基於記憶體、分散式儲存資料庫,下面一起來看一下,希望對大家有幫助。
推薦學習:Redis影片教學
Remote DIctionary Server(Redis) 是一個由Salvatore Sanfilippo 寫的key-value 儲存系統,是跨平台的非關係型資料庫。
Redis 是一個開源的使用ANSI C 語言編寫、遵守BSD 協定、支援網路、可基於記憶體、分散式、可選持久性的鍵值對(Key-Value)儲存資料庫,並提供多種語言的API。
Redis 通常被稱為資料結構伺服器,因為值(value)可以是字串(String)、雜湊(Hash)、列表(list)、集合(sets)和有序集合(sorted sets )等類型。
1、完全基於內存,絕大部分請求是純粹的內存操作,而且非常快速。資料存在記憶體中,類似HashMap,HashMap的優勢就是查找和操作的時間複雜度都是O(1);
2、資料結構簡單,對資料操作也簡單,Redis中的資料結構是專門進行設計的;
3、採用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖定操作,沒有因為可能出現死鎖而導致的效能消耗;
4、使用多路I/O復用模型,非阻塞IO;
5.使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制,因為一般的系統調用系統函數的話,會浪費一定的時間去移動與請求;
6.多路I/O 復用模型
多路I/O復用模型是利用select、poll、epoll 可以同時監察多個流的I/O 事件的能力,在空閒的時候,會把當前線程阻塞掉,當有一個或多個當流有I/O 事件時,就從阻塞態中喚醒,於是程式就會輪詢一遍所有的流(epoll 是只輪詢那些真正發出了事件的流),並且只依次順序的處理就緒的流,這種做法就避免了大量的無用操作。
**這裡「多路」指的是多個網路連接,「重複使用」指的是複用同一個線程。 **採用多路I/O 復用技術可以讓單一執行緒有效率的處理多個連線請求(盡量減少網路IO 的時間消耗),且Redis 在記憶體中操作資料的速度非常快,也就是說記憶體內的操作不會成為影響Redis效能的瓶頸,主要由上述幾點造就了Redis 具有很高的吞吐量。
我們首先要明白,上邊的種種分析,都是為了營造一個Redis很快的氛圍!官方FAQ表示,因為Redis是基於記憶體的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機器記憶體的大小或網路頻寬。既然單線程容易實現,而且CPU不會成為瓶頸,那就順理成章地採用單線程的方案了(畢竟採用多線程會有很多麻煩!)。
redis 127.0.0.1:6379> SET rediskey redis OK redis 127.0.0.1:6379> GET rediskey "redis"
Redis hash 是一個string 類型的field(欄位) 和value(值) 的對應表,hash 特別適合用於儲存物件。
Redis 中每個hash 可以儲存232 - 1 鍵值對(40多億)
Redis列表是簡單的字串列表,按照插入順序排序。你可以加上一個元素到清單的頭部(左邊)或尾部(右邊)
一個清單最多可以包含 232 - 1 個元素 (4294967295, 每個清單超過40億個元素)。
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"
Redis 的 Set 是 String 類型的無序集合。集合成員是唯一的,這意味著集合中不能出現重複的資料。
集合物件的編碼可以是 intset 或 hashtable。
Redis 中集合是透過哈希表實現的,所以添加,刪除,查找的複雜度都是 O(1)。
集合中最大的成員數為 232 - 1 (4294967295, 每個集合可儲存40多億個成員)。
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"
Redis 有序集合和集合一樣也是 string 類型元素的集合,且不允許重複的成員。
不同的是每個元素都會關聯一個 double 類型的分數。 redis 正是透過分數來為集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重複。
集合是透過哈希表實現的,所以添加,刪除,查找的複雜度都是 O(1)。集合中最大的成員數為 232 - 1 (4294967295, 每個集合可儲存40多億個成員)。
Redis 在 2.8.9 版本中新增了 HyperLogLog 結構。
Redis HyperLogLog 是用來做基數統計的演算法,HyperLogLog 的優點是,在輸入元素的數量或體積非常非常大時,計算基數所需的空間總是固定的、而且是很小的。
在 Redis 裡面,每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基 數。這和計算基數時,元素越多耗費記憶體就越多的集合形成鮮明對比。
但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合一樣,傳回輸入的各個元素。
例如資料集{1, 3, 5, 7, 5, 7, 8}, 那麼這個資料集的基數集就是{1, 3 , 5 ,7, 8}, 基數(不重複元素)為5。基數估計就是在誤差可接受的範圍內,快速計算基數。
以下實例示範了HyperLogLog 的工作流程:
//添加指定元素到 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
Redis 發布訂閱(pub/sub) 是一種訊息通訊模式:發送者(pub) 發送訊息,訂閱者(sub) 接收訊息。
Redis 用戶端可以訂閱任意數量的頻道。
下圖展示了頻道 channel1 ,以及訂閱這個頻道的三個客戶端——client2 、 client5 和client1 之間的關係:
以下實例示範了發布訂閱是如何運作的,需要開啟兩個redis-cli 用戶端。
在我們實例中我們建立了訂閱頻道名稱 runoobChat:
redis 127.0.0.1:6379> SUBSCRIBE runoobChat Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "runoobChat" 3) (integer) 1
现在,我们先重新开启个 redis 客户端,然后在同一个频道 runoobChat 发布两次消息,订阅者就能接收到消息。
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 # 订阅者的客户端会显示如下消息 1) "message" 2) "runoobChat" 3) "Redis PUBLISH test" 1) "message" 2) "runoobChat" 3) "Learn redis by runoob.com"
gif 演示如下:
runoobChat
频道。Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
一个事务从开始到执行会经历以下三个阶段:
以下是一个事务的例子, 它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:
redis 127.0.0.1:6379> MULTI OK 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"
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
这是官网上的说明 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 OK 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 已成功不会回滚,set c 还会继续执行。
Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 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"
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。
Redis GEO 操作方法有:
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>
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
Redis Stream 的结构如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容:
每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。
上图解析:
Redis是一種基於客戶端-服務端模型以及請求/回應協定的TCP服務。這表示通常情況下一個請求會遵循以下步驟:
Redis 管道技術可以在服務端未回應時,客戶端可以繼續向服務端發送請求,並最終一次讀取所有服務端的響應。
推薦學習:Redis影片教學
以上是一起來聊聊Redis有什麼優勢和特點的詳細內容。更多資訊請關注PHP中文網其他相關文章!