redis入門(尚矽谷)
1.Redis概述安裝
- Redis是一個開源的key-value儲存系統。
- 和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set --有序集合)和hash(雜湊型別)。
- 這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。
- 在此基礎上,Redis支援各種不同方式的排序。
- 與memcached一樣,為了保證效率,資料都是快取在記憶體中。
- 區別的是Redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案。
- 並且在此基礎上實現了master-slave(主從)同步。
1.1.應用場景
配合關係型資料庫做快取記憶體
- 高頻次,熱門訪問的資料,降低資料庫IO
- 分散式架構,做session共享
多樣的資料結構儲存持久化資料
2. redis安裝
安裝
- 官網:http://redis.io
- 安裝版本:6.2.1 for Linux(redis-6.2.1.tar.gz)
- 安裝C 語言的編譯環境
yum install centos-release-scl scl-utils-build
yum install -y devtoolset-8-toolchain
scl enable devtoolset-8 bash - 測試 gcc版本:sudo gcc --version
- redis-6.2.1.tar.gz放/opt目錄
- 解壓:tar -zxvf redis-6.2.1.tar.gz
- 進入redis-6.2.1目錄執行命令:make
- 如果沒有準備好C語言編譯環境,make 會報錯—Jemalloc/jemalloc.h:沒有那個檔案
- 解決方案:執行make distclean
- 在redis-6.2.1目錄下再次執行make命令(只是編譯好)
- 跳過make test 繼續執行: make install
啟動
前臺啟動(不推薦)
前臺啟動,命令列視窗不能關閉,否則伺服器停止
$ redis-server
後臺啟動(推薦)
- 修改redis.conf配置檔案
- 設定daemonize no改成yes
- 重啟redis-server
啟動客戶端
$ redis-cli -p 6379
redis關閉
$ redis-cli shutdown
Redis介紹相關知識
- 預設16個數據庫,類似陣列下標從0開始,初始預設使用0號庫
- 使用命令 select
來切換資料庫。如: select 8 - 統一密碼管理,所有庫同樣密碼。
- dbsize檢視當前資料庫的key的數量
- flushdb清空當前庫
- flushall通殺全部庫
Redis是單執行緒+多路IO複用技術
多路複用是指使用一個執行緒來檢查多個檔案描述符(Socket)的就緒狀態,比如呼叫select和poll函式,傳入多個檔案描述符,如果有一個檔案描述符就緒,則返回,否則阻塞直到超時。得到就緒狀態後進行真正的操作可以在同一個執行緒裡執行,也可以啟動執行緒執行(比如使用執行緒池)
3. 常用五大資料型別
3.1 3.1.Redis鍵(key)
-
keys *檢視當前庫所有key (匹配:keys *1)
-
exists key判斷某個key是否存在
-
type key 檢視你的key是什麼型別
-
del key 刪除指定的key資料
-
unlink key 根據value選擇非阻塞刪除
-
僅將keys從keyspace元資料中刪除,真正的刪除會在後續非同步操作。
-
expire key 10 10秒鐘:為給定的key設定過期時間
-
ttl key 檢視還有多少秒過期,-1表示永不過期,-2表示已過期
-
select命令切換資料庫
-
dbsize檢視當前資料庫的key的數量
-
flushdb清空當前庫
-
flushall通殺全部庫
3.2 redis字串(string)
3.2.1 簡介
- String是Redis最基本的型別,你可以理解成與Memcached一模一樣的型別,一個key對應一個value。
- String型別是二進位制安全的。意味著Redis的string可以包含任何資料。比如jpg圖片或者序列化的物件。
- String型別是Redis最基本的資料型別,一個Redis中字串value最多可以是512M
3.2.2 常用命令
set
*NX:當資料庫中key不存在時,可以將key-value新增資料庫
*XX:當資料庫中key存在時,可以將key-value新增資料庫,與NX引數互斥
*EX:key的超時秒數
*PX:key的超時毫秒數,與EX互斥
-
get
查詢對應鍵值 -
append
將給定的 追加到原值的末尾 -
strlen
獲得值的長度 -
setnx
只有在 key 不存在時 設定 key 的值 -
mset
.....
同時設定一個或多個 key-value對 -
mget
.....
同時獲取一個或多個 value -
msetnx
.....
同時設定一個或多個 key-value 對,當且僅當所有給定 key 都不存在。 -
getrange
<起始位置><結束位置>
獲得值的範圍,類似java中的substring,前包,後包 -
setrange
<起始位置>
用覆寫 所儲存的字串值,從<起始位置>開始(索引從0開始)。 -
setex
<過期時間>
設定鍵值的同時,設定過期時間,單位秒。 -
getset
以新換舊,設定了新值同時獲得舊值 -
incr
將 key 中儲存的數字值增1
只能對數字值操作,如果為空,新增值為1 -
decr
將 key 中儲存的數字值減1
只能對數字值操作,如果為空,新增值為-1 -
incrby / decrby
<步長>將 key 中儲存的數字值增減。自定義步長。
原子性
所謂原子操作是指不會被執行緒排程機制打斷的操作;
這種操作一旦開始,就一直執行到結束,中間不會有任何 context switch (切換到另一個執行緒)。
(1)在單執行緒中, 能夠在單條指令中完成的操作都可以認為是"原子操作",因為中斷只能發生於指令之間。
(2)在多執行緒中,不能被其它程序(執行緒)打斷的操作就叫原子操作。
Redis單命令的原子性主要得益於Redis的單執行緒。
3.2.3 資料結構
String的資料結構為簡單動態字串(Simple Dynamic String,縮寫SDS)。是可以修改的字串,內部結構實現上類似於Java的ArrayList,採用預分配冗餘空間的方式來減少記憶體的頻繁分配.
如圖中所示,內部為當前字串實際分配的空間capacity一般要高於實際字串長度len。當字串長度小於1M時,擴容都是加倍現有的空間,如果超過1M,擴容時一次只會多擴1M的空間。需要注意的是字串最大長度為512M。
3.3 redis列表(List)
3.3.1 簡介
單鍵多值
Redis 列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素到列表的頭部(左邊)或者尾部(右邊)。
它的底層實際是個雙向連結串列,對兩端的操作效能很高,通過索引下標的操作中間的節點效能會較差。
3.3.2 常用命令
-
lpush/rpush
.... 從左邊/右邊插入一個或多個值。 -
lpop/rpop
從左邊/右邊吐出一個值。值在鍵在,值光鍵亡。 -
rpoplpush
從 列表右邊吐出一個值,插到 列表左邊。 -
lrange
按照索引下標獲得元素(從左到右) -
lrange mylist 0 -1 0左邊第一個,-1右邊第一個,(0-1表示獲取所有)
-
lindex
按照索引下標獲得元素(從左到右) -
llen
獲得列表長度 -
linsert
before 在 的後面插入 插入值 -
lrem
從左邊刪除n個value(從左到右) -
lset
將列表key下標為index的值替換成value
3.3.3 資料結構
List的資料結構為快速連結串列quickList。
首先在列表元素較少的情況下會使用一塊連續的記憶體儲存,這個結構是ziplist,也即是壓縮列表。
它將所有的元素緊挨著一起儲存,分配的是一塊連續的記憶體。
當資料量比較多的時候才會改成quicklist。
因為普通的連結串列需要的附加指標空間太大,會比較浪費空間。比如這個列表裡存的只是int型別的資料,結構上還需要兩個額外的指標prev和next。
Redis將連結串列和ziplist結合起來組成了quicklist。也就是將多個ziplist使用雙向指標串起來使用。這樣既滿足了快速的插入刪除效能,又不會出現太大的空間冗餘。
3.4 redis集合(Set)
3.4.1 簡介
Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要儲存一個列表資料,又不希望出現重複資料時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的。
Redis的Set是string型別的無序集合。它底層其實是一個value為null的hash表,所以新增,刪除,查詢的複雜度都是O(1)。
一個演算法,隨著資料的增加,執行時間的長短,如果是O(1),資料增加,查詢資料的時間不變。
3.4.2 常用命令
- sadd
.....
將一個或多個 member 元素加入到集合 key 中,已經存在的 member 元素將被忽略 - smembers
取出該集合的所有值。 - sismember
判斷集合 是否為含有該 值,有1,沒有0 - scard
返回該集合的元素個數。 - srem
.... 刪除集合中的某個元素。 - spop
隨機從該集合中吐出一個值。 - srandmember
隨機從該集合中取出n個值。不會從集合中刪除 。 - smove
- sinter
返回兩個集合的交集元素。 - sunion
返回兩個集合的並集元素。 - sdiff
返回兩個集合的差集元素(key1中的,不包含key2中的)
3.4.3 資料結構
Set資料結構是dict字典,字典是用雜湊表實現的。
Java中HashSet的內部實現使用的是HashMap,只不過所有的value都指向同一個物件。Redis的set結構也是一樣,它的內部也使用hash結構,所有的value都指向同一個內部值。
3.5 redis雜湊(hash)
3.5.1 簡介
Redis hash 是一個鍵值對集合。
Redis hash是一個string型別的field和value的對映表,hash特別適合用於儲存物件。
類似Java裡面的Map<String,Object>
使用者ID為查詢的key,儲存的value使用者物件包含姓名,年齡,生日等資訊,如果用普通的key/value結構來儲存
主要有以下2種儲存方式:
每次修改使用者的某個屬性需要,先反序列化改好後再序列化回去。開銷較大。
使用者ID資料冗餘
通過 key(使用者ID) + field(屬性標籤) 就可以操作對應屬性資料了,既不需要重複儲存資料,也不會帶來序列化和併發修改控制的問題
3.5.2 常用命令
- hset
給 集合中的 鍵賦值 - hget
從 集合 取出 value - hmset
... 批量設定hash的值 - hexists
檢視雜湊表 key 中,給定域 field 是否存在。 - hkeys
列出該hash集合的所有field - hvals
列出該hash集合的所有value - hincrby
為雜湊表 key 中的域 field 的值加上增量 1 -1 - hsetnx
將雜湊表 key 中的域 field 的值設定為 value ,當且僅當域 field 不存在 .
3.5.3 資料結構
Hash型別對應的資料結構是兩種:ziplist(壓縮列表),hashtable(雜湊表)。當field-value長度較短且個數較少時,使用ziplist,否則使用hashtable。
3.6 Redis有序集合Zset(sorted set)
3.6.1 簡介
- Redis有序集合zset與普通集合set非常相似,是一個沒有重複元素的字串集合。
- 不同之處是有序集合的每個成員都關聯了一個評分(score),這個評分(score)被用來按照從最低分到最高分的方式排序集合中的成員。集合的成員是唯一的,但是評分可以是重複。
- 因為元素是有序的, 所以你也可以很快的根據評分(score)或者次序(position)來獲取一個範圍的元素。
- 訪問有序集合的中間元素也是非常快的,因此你能夠使用有序集合作為一個沒有重複成員的智慧列表。
3.6.2 常用命令
- zadd
…
將一個或多個 member 元素及其 score 值加入到有序集 key 當中。 - zrange
[WITHSCORES]
返回有序集 key 中,下標在之間的元素
帶WITHSCORES,可以讓分數一起和值返回到結果集。 - zrangebyscore key minmax [withscores] [limit offset count]
返回有序集 key 中,所有 score 值介於 min 和 max 之間(包括等於 min 或 max )的成員。有序整合員按 score 值遞增(從小到大)次序排列。 - zrevrangebyscore key maxmin [withscores] [limit offset count]
同上,改為從大到小排列。 - zincrby
為元素的score加上增量 - zrem
刪除該集合下,指定值的元素 - zcount
統計該集合,分數區間內的元素個數 - zrank
返回該值在集合中的排名,從0開始
案例:如何利用zset實現一個文章訪問量的排行榜?
3.6.3 資料結構
SortedSet(zset)是Redis提供的一個非常特別的資料結構,一方面它等價於Java的資料結構Map<String, Double>,可以給每一個元素value賦予一個權重score,另一方面它又類似於TreeSet,內部的元素會按照權重score進行排序,可以得到每個元素的名次,還可以通過score的範圍來獲取元素的列表。
zset底層使用了兩個資料結構
(1)hash,hash的作用就是關聯元素value和權重score,保障元素value的唯一性,可以通過元素value找到相應的score值。
(2)跳躍表,跳躍表的目的在於給元素value排序,根據score的範圍獲取元素列表。
3.6.4 跳躍表
1、簡介
有序集合在生活中比較常見,例如根據成績對學生排名,根據得分對玩家排名等。對於有序集合的底層實現,可以用陣列、平衡樹、連結串列等。陣列不便元素的插入、刪除;平衡樹或紅黑樹雖然效率高但結構複雜;連結串列查詢需要遍歷所有效率低。Redis採用的是跳躍表。跳躍表效率堪比紅黑樹,實現遠比紅黑樹簡單。
2、例項
對比有序連結串列和跳躍表,從連結串列中查詢出51
(1)有序連結串列
要查詢值為51的元素,需要從第一個元素開始依次查詢、比較才能找到。共需要6次比較。
(2)跳躍表
從第2層開始,1節點比51節點小,向後比較。
21節點比51節點小,繼續向後比較,後面就是NULL了,所以從21節點向下到第1層
在第1層,41節點比51節點小,繼續向後,61節點比51節點大,所以從41向下
在第0層,51節點為要查詢的節點,節點被找到,共查詢4次。
從此可以看出跳躍表比有序連結串列效率要高
4 redis配置檔案(redis.conf)
4.1.###Units單位###
配置大小單位,開頭定義了一些基本的度量單位,只支援bytes,不支援bit
大小寫不敏感
4.2.###INCLUDES包含###
類似jsp中的include,多例項的情況可以把公用的配置檔案提取出來
4.3.###網路相關配置
4.3.1.bind
- 預設情況bind=127.0.0.1只能接受本機的訪問請求
- 不寫的情況下,無限制接受任何ip地址的訪問
- 生產環境肯定要寫你應用伺服器的地址;伺服器是需要遠端訪問的,所以需要將其註釋掉
- 如果開啟了protected-mode,那麼在沒有設定bind ip且沒有設密碼的情況下,Redis只允許接受本機的響應
儲存配置,停止服務,重啟啟動檢視程序,不再是本機訪問了。
4.3.2.protected-mode
將本機訪問保護模式設定no
4.3.3.Port
埠號,預設 6379
4.3.4.tcp-backlog
設定tcp的backlog,backlog其實是一個連線佇列,backlog佇列總和=未完成三次握手佇列 + 已經完成三次握手佇列。
在高併發環境下你需要一個高backlog值來避免慢客戶端連線問題。
注意Linux核心會將這個值減小到/proc/sys/net/core/somaxconn的值(128),所以需要確認增大/proc/sys/net/core/somaxconn和/proc/sys/net/ipv4/tcp_max_syn_backlog(128)兩個值來達到想要的效果
4.3.5.timeout
一個空閒的客戶端維持多少秒會關閉,0表示關閉該功能。即永不關閉。
4.3.6.tcp-keepalive
對訪問客戶端的一種心跳檢測,每個n秒檢測一次。
單位為秒,如果設定為0,則不會進行Keepalive檢測,建議設定成60
4.4.###GENERAL通用###
4.4.1.daemonize
是否為後臺程序,設定為yes
守護程序,後臺啟動
4.4.2.pidfile
存放pid檔案的位置,每個例項會產生一個不同的pid檔案
loglevel
指定日誌記錄級別,Redis總共支援四個級別:debug、verbose、notice、warning,預設為notice
四個級別根據使用階段來選擇,生產環境選擇notice 或者warning
logfile
日誌檔名稱
4.4.5.databases 16
設定庫的數量 預設16,預設資料庫為0,可以使用SELECT
4.5.###SECURITY安全###
4.5.1.設定密碼
訪問密碼的檢視、設定和取消
在命令中設定密碼,只是臨時的。重啟redis伺服器,密碼就還原了。
永久設定,需要再配置檔案中進行設定。
4.6.#### LIMITS限制
4.6.1.maxclients
- 設定redis同時可以與多少個客戶端進行連線。
- 預設情況下為10000個客戶端。
- 如果達到了此限制,redis則會拒絕新的連線請求,並且向這些連線請求方發出“max number of clients reached”以作迴應。
maxmemory
- 建議必須設定,否則,將記憶體佔滿,造成伺服器宕機
- 設定redis可以使用的記憶體量。一旦到達記憶體使用上限,redis將會試圖移除內部資料,移除規則可以通過maxmemory-policy來指定。
- 如果redis無法根據移除規則來移除記憶體中的資料,或者設定了“不允許移除”,那麼redis則會針對那些需要申請記憶體的指令返回錯誤資訊,比如SET、LPUSH等。
- 但是對於無記憶體申請的指令,仍然會正常響應,比如GET等。如果你的redis是主redis(說明你的redis有從redis),那麼在設定記憶體使用上限時,需要在系統中留出一些記憶體空間給同步佇列快取,只有在你設定的是“不移除”的情況下,才不用考慮這個因素
4.6.3.maxmemory-policy
- volatile-lru:使用LRU演算法移除key,只對設定了過期時間的鍵;(最近最少使用)
- allkeys-lru:在所有集合key中,使用LRU演算法移除key
- volatile-random:在過期集合中移除隨機的key,只對設定了過期時間的鍵
- allkeys-random:在所有集合key中,移除隨機的key
- volatile-ttl:移除那些TTL值最小的key,即那些最近要過期的key
- noeviction:不進行移除。針對寫操作,只是返回錯誤資訊
4.6.4.maxmemory-samples
- 設定樣本數量,LRU演算法和最小TTL演算法都並非是精確的演算法,而是估算值,所以你可以設定樣本的大小,redis預設會檢查這麼多個key並選擇其中LRU的那個。
- 一般設定3到7的數字,數值越小樣本越不準確,但效能消耗越小。
5.Redis的釋出和訂閱
5.1.什麼是釋出和訂閱
Redis 釋出訂閱 (pub/sub) 是一種訊息通訊模式:傳送者 (pub) 傳送訊息,訂閱者 (sub) 接收訊息。
Redis 客戶端可以訂閱任意數量的頻道
5.2.Redis的釋出和訂閱
1、客戶端可以訂閱頻道如下圖
2、當給這個頻道釋出訊息後,訊息就會發送給訂閱的客戶端
5.3.釋出訂閱命令列實現
1、開啟一個客戶端訂閱channel1
SUBSCRIBEchannel1
2、開啟另一個客戶端,給channel1釋出訊息hello
publish channel1 hello
返回的1是訂閱者數量
3、開啟第一個客戶端可以看到傳送的訊息
注:釋出的訊息沒有持久化,如果在訂閱的客戶端收不到hello,只能收到訂閱後釋出的訊息