redis使用
本文記錄學習redis學習的相關內容文章目錄
- redis使用
- 一、下載安裝
- 1.下載
- 2.安裝
- 二、啟動運行
- 1.前臺啟動
- 2.后臺啟動
- 三、基本資料型別
- 1.redis-key命令
- 2.字串String
- 2.串列List
- 3.集合Set
- 4.哈希Hash
- 5.有序集合Zset
- 四、三種特殊資料型別
- 五、事務
- 1.redis沒有事務隔離級別的概念
- 2.redis不保證原子性
- 3.redis事務的三個階段
- 4.示例
- 六、持久化-RDB
- 1.作業原理
- 2.觸發機制
- 3.優缺點
- 七、持久化-AOF
- 1.作業原理
- 2.優缺點
- 八、Redis發布訂閱(基本不用)
- 九、Redis主從復制
- 十、Redis哨兵模式
- 十一、快取穿透與雪崩
- 1.快取穿透(查不到)
- 2.快取擊穿(量太大,快取過期)
- 3.快取雪崩
一、下載安裝
1.下載
直接去http://www.redis.cn/
這里以redis-5.0.7.tar.gz為例
下載完成后上傳到/usr目錄下
2.安裝
進入/usr目錄
解壓
[root@VM-0-2-centos usr]# tar -zxvf redis-5.0.7.tar.gz -C /usr/
移動到local目錄下并改下名字
[root@VM-0-2-centos usr]# mv redis-5.0.7 /usr/local/redis
進入/usr/local/redis目錄下執行安裝命令
因為redis是c語言撰寫的,在此步驟之前需要下載gcc編譯器
yum install gcc-c++
如果已經安裝過了直接執行如下命名
[root@VM-0-2-centos redis]# make
#然后
[root@VM-0-2-centos redis]# make install
redis默認安裝到/usr/local/bin目錄下
移動到/usr/local/redis
[root@VM-0-2-centos local]# mv bin/ redis/
二、啟動運行
1.前臺啟動
進入/usr/local/redis/bin目錄下
執行
[root@VM-0-2-centos bin]# ./redis-server

重新開一個頁面輸入如下命令
查看6379存活即為啟動成功
如果想關閉redis
在圖1界面Ctrl+C即可
[外鏈圖片轉存中…(img-rxV9GE0q-16124304165659416.png)
如此即為退出成功
以特定的組態檔啟動
[root@VM-0-2-centos redis]# ./bin/redis-server redis.conf
正常我們在學習作業時候 要把組態檔備份一下 養成良好習慣
[root@VM-0-2-centos redis]# cp redis.conf redis.conf.bak
2.后臺啟動
vim打開編輯redis.conf
[root@VM-0-2-centos redis]# vim redis.conf
找到daemonize配置改為yes

# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes
保存退出
執行啟動命令
[root@VM-0-2-centos redis]# ./bin/redis-server redis.conf
25528:C 04 Feb 2021 17:22:28.557 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
25528:C 04 Feb 2021 17:22:28.557 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=25528, just started
25528:C 04 Feb 2021 17:22:28.557 # Configuration loaded
查看啟動正常

本機連接redis
輸入KEYS *(此時redis中并無資料,所以回傳empty)
[root@VM-0-2-centos redis]# ./bin/redis-cli -p 6379
127.0.0.1:6379> KEYS *
(empty list or set)
三、基本資料型別
redis是一個基于記憶體亦可持久化(日志檔案)、key-value的資料庫,
它支持存盤得value型別更多,字串String、鏈表list、集合set、有序集合zSet、哈希型別hash
1.redis-key命令
查看當前庫所有key
127.0.0.1:6379> KEYS *
(empty list or set)
設定key
127.0.0.1:6379> SET name zhangchi
OK
127.0.0.1:6379> KEYS *
2) "name"
移動資料到指定資料庫
127.0.0.1:6379> MOVE name 1 //移動資料到指定資料庫 1是資料庫索引
(integer) 1 //受影響行數
127.0.0.1:6379> KEYS *
(empty list or set) //資料庫0中不存在name這個key
127.0.0.1:6379> SELECT 1 //切換到資料庫1
OK
127.0.0.1:6379[1]> KEYS *
1) "name" //此時資料已經被移動過來了
判斷當前庫是否存在某個key
127.0.0.1:6379[1]> SELECT 0
OK
127.0.0.1:6379> EXISTS name
(integer) 0 //沒有回傳0(也可理解為滿足條件個數)
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> EXISTS name
(integer) 1 //有回傳1(也可理解為滿足條件個數)
127.0.0.1:6379[1]>
洗掉資料
127.0.0.1:6379[1]> DEL name
(integer) 1 //存在資料被洗掉回傳1(也可理解為滿足條件個數)
127.0.0.1:6379[1]> DEL name
(integer) 0 //洗掉不存在資料回傳0(也可理解為滿足條件個數)
設定key失效時間
--方式1--
127.0.0.1:6379> SET name zhangchi
OK
127.0.0.1:6379> EXPIRE name 20 //設定失效時間為20秒
(integer) 1
127.0.0.1:6379> ttl name //查詢剩余失效時間
(integer) 18
127.0.0.1:6379> ttl name
(integer) 15
127.0.0.1:6379> ttl name
(integer) 7
127.0.0.1:6379> ttl name
(integer) -2 //-2表示已經失效了
127.0.0.1:6379> SET name zhangchi
OK
127.0.0.1:6379> ttl name
(integer) -1 //回傳-1表示未設定失效時間(永不失效)
--方式2--
127.0.0.1:6379> EXPIREAT name 1612496655 //允許以時間戳的形式設定
(integer) 1
127.0.0.1:6379> ttl name
(integer) 71
127.0.0.1:6379> ttl name
(integer) 70
--注意:此方式設定的時間戳如果小于當前時間會直接失效 不會報錯--
查看key對應的value資料型別
127.0.0.1:6379> SET name zhangchi
OK
127.0.0.1:6379> TYPE name
string //有key結果的話回傳資料型別
127.0.0.1:6379> TYPE name0
none //無key的話回傳none
重命名key
--RENAME--
127.0.0.1:6379> RENAME name nm
OK
127.0.0.1:6379> KEYS *
1) "nm"
127.0.0.1:6379> RENAME name nm
(error) ERR no such key //沒有key則報錯
2.字串String
追加字串
127.0.0.1:6379> SET name zhangchi
OK
127.0.0.1:6379> APPEND name 123
(integer) 11 //回傳的是新字串長度
127.0.0.1:6379> GET name
"zhangchi123"
指定的key對應的value加一減一(可以用于做閱讀量記錄)
127.0.0.1:6379> DECR name //不是數字型別揮著越界了 會報錯
(error) ERR value is not an integer or out of range
127.0.0.1:6379> SET age 27
OK
127.0.0.1:6379> DECR age //減1
(integer) 26
127.0.0.1:6379> INCR age //加1
(integer) 27
指定的key對應的value加n減n
127.0.0.1:6379> DECRBY age 5 //減5
(integer) 22
127.0.0.1:6379> INCRBY age 5 //加5
(integer) 27
為數值加上浮點型數值
127.0.0.1:6379> INCRBYFLOAT age 0.5 //沒有DECRBYFLOAT陳述句
"27.5"
獲取字串長度
127.0.0.1:6379> STRLEN name (String length縮寫)
(integer) 11
截取字串的(左閉右閉)
127.0.0.1:6379> GETRANGE name 0 7
"zhangchi" //正常獲取
127.0.0.1:6379> GETRANGE name 0 15
"zhangchi123" //如果右邊超過了長度不會報錯,按最大值取
127.0.0.1:6379> GETRANGE name 16 15
"" //這樣也不會報錯
127.0.0.1:6379> GETRANGE name -16 15
"zhangchi123" //同理 這樣寫也沒問題
用指定的value 替換key中 offset開始的值
127.0.0.1:6379> GET name
"zhangchi000"
127.0.0.1:6379> SETRANGE name 0 ZhangChi
(integer) 11 //下標從0開始逐個替換
127.0.0.1:6379> GET name
"ZhangChi000"
127.0.0.1:6379> SETRANGE name 15 ZhangChi
(integer) 23
127.0.0.1:6379> GET name
"ZhangChi000\x00\x00\x00\x00ZhangChi" //替換的字串右邊越界了的話 會自動補充null
127.0.0.1:6379> SETRANGE name -15 ZhangChi
(error) ERR offset is out of range //左邊越界了會報錯
設定key為新值,并回傳老值
127.0.0.1:6379> GET name
"ZhangChi000\x00\x00\x00\x00ZhangChi"
127.0.0.1:6379> GETSET name zhangchi
"ZhangChi000\x00\x00\x00\x00ZhangChi"
127.0.0.1:6379> GET name
"zhangchi"
僅當key不存在時set(SET if Not eXists)
127.0.0.1:6379> KEYS *
1) "age"
2) "name"
127.0.0.1:6379> SETNX age 22
(integer) 0 //key存在不會更新
127.0.0.1:6379> GET age
"28"
127.0.0.1:6379> SETNX gender 男
(integer) 1 //key不存在不會設定
127.0.0.1:6379> GET gender
"\xe7\x94\xb7"
set 鍵值對并設定過期時間
127.0.0.1:6379> SETEX age 20 18
OK
127.0.0.1:6379> GET age
"18"
127.0.0.1:6379> ttl age
(integer) 8
127.0.0.1:6379> ttl age
(integer) 5
127.0.0.1:6379> ttl age
(integer) -2
127.0.0.1:6379> GET age
(nil)
批量設定key-value
127.0.0.1:6379> FLUSHALL //清空所有快取
OK
127.0.0.1:6379> MSET name zhangchi age 18
OK
127.0.0.1:6379> KEYS *
1) "age"
2) "name"
批量設定鍵值對,僅當所有key都不存在成功
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> MSET name zhangchi age 18
OK
127.0.0.1:6379> MSETNX name zhangchi gender 男
(integer) 0
127.0.0.1:6379> KEYS *
1) "age"
2) "name"
批量獲取多個key保存的值
127.0.0.1:6379> MGET name age
1) "zhangchi"
2) "18"
以毫秒為單位set鍵值對失效時間
127.0.0.1:6379> PSETEX name 20000 zhangchi
OK
127.0.0.1:6379> ttl name
(integer) 14
127.0.0.1:6379> ttl name
(integer) -2
2.串列List
redis中鏈表底層的實作是資料結構中的雙向鏈表,所以可以對該資料結構做限制操作,實作佇列、堆疊,
因為是雙端操作,所以串列的操作命令一般都是Rxxx或者Lxxx形式的,
可以用于
訊息佇列(LPUSH RPOP)
堆疊(LPUSH LPOP)
插入資料(左右)
127.0.0.1:6379> LPUSH name zhangchi001 zhangchi002 zhangchi003 //左插(可以批量)
(integer) 3
127.0.0.1:6379> LRANGE name 0 -1 //查詢全部
1) "zhangchi003"
2) "zhangchi002"
3) "zhangchi001"
127.0.0.1:6379> RPUSH name zhangchi000 //右插(可以批量)
(integer) 4
127.0.0.1:6379> LRANGE name 0 -1 //獲取全部資料
1) "zhangchi003"
2) "zhangchi002"
3) "zhangchi001"
4) "zhangchi000"
查詢資料
127.0.0.1:6379> LRANGE name 0 -1 //查詢所有 -1倒數第n個元素的下標
1) "zhangchi004"
2) "zhangchi003"
3) "zhangchi002"
4) "zhangchi001"
5) "zhangchi000"
127.0.0.1:6379> LRANGE name 0 2 //0-2閉區間
1) "zhangchi004"
2) "zhangchi003"
3) "zhangchi002"
127.0.0.1:6379> LRANGE name 0 15 //
1) "zhangchi004"
2) "zhangchi003"
3) "zhangchi002"
4) "zhangchi001"
5) "zhangchi000"
127.0.0.1:6379> LRANGE name -1 15
1) "zhangchi000"
127.0.0.1:6379> LRANGE name -1 1
(empty list or set)
127.0.0.1:6379> LRANGE name -1 4
1) "zhangchi000"
127.0.0.1:6379> LRANGE name -1 -1
1) "zhangchi000"
127.0.0.1:6379> LRANGE name -2 -1 //倒數第2個到倒數第1個
1) "zhangchi001"
2) "zhangchi000"
向存在的key中push值
127.0.0.1:6379> LPUSHX name zhangchi 005
(integer) 7 //存在回傳元素個數
127.0.0.1:6379> LPUSHX names zhangchi 005
(integer) 0 //不存在回傳0
127.0.0.1:6379> LRANGE name 0 -1
1) "005"
2) "zhangchi"
3) "zhangchi004"
4) "zhangchi003"
5) "zhangchi002"
6) "zhangchi001"
7) "zhangchi000"
127.0.0.1:6379> LRANGE names 0 -1
(empty list or set)
串列指定元素前后插入
127.0.0.1:6379> LINSERT name BEFORE 0 000
(integer) -1 //插入到沒有的元素附近回傳-1
127.0.0.1:6379> LRANGE name 0 -1
1) "005"
2) "zhangchi"
3) "zhangchi004"
4) "zhangchi003"
5) "zhangchi002"
6) "zhangchi001"
7) "zhangchi000"
127.0.0.1:6379> LINSERT name BEFORE 005 000
(integer) 8 //插入005前面000
127.0.0.1:6379> LINSERT name AFTER 005 000
(integer) 9 //插入005后面000
127.0.0.1:6379> LINSERT name AFTER 005 000
(integer) 10 //插入005后面000
127.0.0.1:6379> LINSERT name AFTER 000 0000
(integer) 11 //插入000前面0000(多個的話 以第一個為準)
127.0.0.1:6379> LRANGE name 0 -1
1) "000"
2) "0000"
3) "005"
4) "000"
5) "000"
6) "zhangchi"
7) "zhangchi004"
8) "zhangchi003"
9) "zhangchi002"
10) "zhangchi001"
11) "zhangchi000"
查看串列長度
127.0.0.1:6379> LLEN name
(integer) 11 //串列存在回傳長度
127.0.0.1:6379> LLEN names
(integer) 0 //不存在回傳0
通過索引獲取元素值
127.0.0.1:6379> LLEN names
(integer) 0
127.0.0.1:6379> LINDEX name 0
"000"
127.0.0.1:6379> LINDEX names 0
(nil) //沒有回傳nil
通過索引設定元素值
127.0.0.1:6379> LSET name 0 123456
OK
127.0.0.1:6379> LRANGE name 0 -1
1) "123456"
2) "0000"
3) "005"
4) "000"
5) "000"
6) "zhangchi"
7) "zhangchi004"
8) "zhangchi003"
9) "zhangchi002"
10) "zhangchi001"
11) "zhangchi000"
洗掉元素并回傳洗掉的值
127.0.0.1:6379> LRANGE name 0 -1
1) "123456"
2) "0000"
3) "005"
4) "000"
5) "000"
6) "zhangchi"
7) "zhangchi004"
8) "zhangchi003"
9) "zhangchi002"
10) "zhangchi001"
11) "zhangchi000"
127.0.0.1:6379> LPOP name //左邊洗掉
"123456"
127.0.0.1:6379> LRANGE name 0 -1
1) "0000"
2) "005"
3) "000"
4) "000"
5) "zhangchi"
6) "zhangchi004"
7) "zhangchi003"
8) "zhangchi002"
9) "zhangchi001"
10) "zhangchi000"
127.0.0.1:6379> RPOP name //右邊洗掉
"zhangchi000"
127.0.0.1:6379> LRANGE name 0 -1
1) "0000"
2) "005"
3) "000"
4) "000"
5) "zhangchi"
6) "zhangchi004"
7) "zhangchi003"
8) "zhangchi002"
9) "zhangchi001"
將一個串列的尾洗掉加入到另一個串列的頭
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> LPUSH names zhangchi001 zhangchi002
(integer) 2
127.0.0.1:6379> LPUSH age 18 192
(integer) 2
127.0.0.1:6379> RPOPLPUSH names age
"zhangchi001" //回傳被移動的元素
127.0.0.1:6379> LRANGE names 0 -1
1) "zhangchi002"
127.0.0.1:6379> LRANGE age 0 -1
1) "zhangchi001"
2) "192"
3) "18"
通過下標截取指定范圍的串列
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> LPUSH names zhangchi001 zhangchi002 zhangchi003
(integer) 3
127.0.0.1:6379> LRANGE names 0 -1
1) "zhangchi003"
2) "zhangchi002"
從前(后或者所有)洗掉指定個數元素
127.0.0.1:6379> LPUSH age 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
(integer) 15
127.0.0.1:6379> LRANGE age 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
6) "5"
7) "4"
8) "3"
9) "2"
10) "1"
11) "5"
12) "4"
13) "3"
14) "2"
15) "1"
127.0.0.1:6379> LREM age 1 4 //從前面開始洗掉1個4
(integer) 1
127.0.0.1:6379> LRANGE age 0 -1
1) "5"
2) "3"
3) "2"
4) "1"
5) "5"
6) "4"
7) "3"
8) "2"
9) "1"
10) "5"
11) "4"
12) "3"
13) "2"
14) "1"
127.0.0.1:6379> LREM age -2 5 //從后面開始洗掉2個5
(integer) 2
127.0.0.1:6379> LRANGE age 0 -1
1) "5"
2) "3"
3) "2"
4) "1"
5) "4"
6) "3"
7) "2"
8) "1"
9) "4"
10) "3"
11) "2"
12) "1"
127.0.0.1:6379> LREM age 0 1 //洗掉所有1
(integer) 3
127.0.0.1:6379> LRANGE age 0 -1
1) "5"
2) "3"
3) "2"
4) "4"
5) "3"
6) "2"
7) "4"
8) "3"
9) "2"
移除串列第一個值,如果沒有的話等帶一定時間后回傳nil
127.0.0.1:6379> BLPOP age 100 //移除第一個元素,如果沒資料則等100秒后回傳nil
//新開一個視窗
127.0.0.1:6379> LPUSH age 1
(integer) 1
//此時第一個視窗列印如下
1) "age"
2) "1"
127.0.0.1:6379> BRPOP age 10 //移除最后一個元素,如果沒資料則等100秒后回傳nil
(nil)
(10.02s)
移動串列最后一個值到另一個串列頭,如果沒有的話等帶一定時間后回傳nil
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> BRPOPLPUSH age ageext 100 //將age最后一個元素移動到ageext頭并回傳移動的元素 超過100秒回傳nil
//新開一個視窗
127.0.0.1:6379> LPUSH age 1
(integer) 1
//原來視窗回傳如下資訊
"1"
(2.99s)
127.0.0.1:6379> LRANGE age 0 -1
(empty list or set)
127.0.0.1:6379> LRANGE ageext 0 -1
1) "1"
3.集合Set
redis的set集合是String型別的無需集合,底層使用的是hash表實作的,值唯一,
最大容量2^32-1
命令都以S開頭
添加一個、多個成員
127.0.0.1:6379> SADD names zhangchi001 zhangchi002
(integer) 2 //回傳集合元素個數
127.0.0.1:6379> SMEMBERS names //遍歷元素
1) "zhangchi001"
2) "zhangchi002"
獲取集合的成員數量
127.0.0.1:6379> SCARD names
(integer) 2
回傳集合中所有的成員
127.0.0.1:6379> smembers names
1) "zhangchi001"
2) "zhangchi002"
查詢set中是否包含某個元素
127.0.0.1:6379> SISMEMBER names zhangchi001
(integer) 1 //有的話回傳條數
127.0.0.1:6379> SISMEMBER names zhangchi
(integer) 0 //沒有回傳0
隨機回傳集合中n個元素
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004 zc005 zc006 zc007
(integer) 7
127.0.0.1:6379> SRANDMEMBER names 4 //隨機回傳names中4個元素
1) "zc002"
2) "zc001"
3) "zc007"
4) "zc006"
127.0.0.1:6379> SRANDMEMBER names //不指定個數的話 就是一條
"zc002"
隨機洗掉n個元素并回傳被洗掉元素
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004 zc005 zc006 zc007
(integer) 7
127.0.0.1:6379> SPOP names 2 //從names中隨機洗掉兩個元素并回傳
1) "zc004"
2) "zc005"
127.0.0.1:6379> SMEMBERS names
1) "zc003"
2) "zc001"
3) "zc002"
4) "zc007"
5) "zc006"
127.0.0.1:6379> SPOP names //不指定被洗掉個數則默認1條
"zc006"
127.0.0.1:6379> SMEMBERS names
1) "zc003"
2) "zc001"
3) "zc002"
4) "zc007"
將元素從A集合移動到B集合
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002
(integer) 2
127.0.0.1:6379> SMOVE names nms zc001
(integer) 1
127.0.0.1:6379> SMEMBERS names
1) "zc002"
127.0.0.1:6379> SMEMBERS nms
1) "zc001"
洗掉集合一個或多個元素
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004 zc005 zc006 zc007
(integer) 7
127.0.0.1:6379> SREM names zc001 zc002
(integer) 2 //回傳被洗掉的個數
127.0.0.1:6379> SMEMBERS names
1) "zc005"
2) "zc003"
3) "zc007"
4) "zc004"
5) "zc006"
回傳集合A相對于集合B、C、D…的并集的差集
A-B-C-D
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004
(integer) 4
127.0.0.1:6379> SADD nms zc004 zc005 zc006 zc007
(integer) 4
127.0.0.1:6379> SDIFF names nms //names-nms
1) "zc003"
2) "zc001"
3) "zc002"
127.0.0.1:6379> SADD ns zc000 zc001 zc002 zc005
(integer) 4
127.0.0.1:6379> SDIFF names nms ns //names-nms-ns
1) "zc003"
回傳集合A相對于集合B、C、D…的并集的差集,并把結果賦值給新的結合O
O=A-B-C-D
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004
(integer) 4
127.0.0.1:6379> SADD nms zc004 zc005 zc006 zc007
(integer) 4
127.0.0.1:6379> SADD ns zc000 zc001 zc002 zc005
(integer) 4
127.0.0.1:6379> SDIFFSTORE newnames names nms ns
(integer) 1
127.0.0.1:6379> SMEMBERS newnames
1) "zc003"
回傳所有集合交集
A∩B∩C…
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004
(integer) 4
127.0.0.1:6379> SADD nms zc004 zc005 zc006 zc007
(integer) 4
127.0.0.1:6379> SINTER names nms
1) "zc004"
回傳所有集合交集,并保存到新的集合中O
O = A∩B∩C…
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004
(integer) 4
127.0.0.1:6379> SADD nms zc004 zc005 zc006 zc007
(integer) 4
127.0.0.1:6379> SINTERSTORE newnames names nms
(integer) 1
127.0.0.1:6379> SMEMBERS newnames
1) "zc004"
回傳所有集合并集
A∪B∪C…
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004
(integer) 4
127.0.0.1:6379> SADD nms zc004 zc005 zc006 zc007
(integer) 4
127.0.0.1:6379> SADD ns zc000 zc001 zc002 zc005
(integer) 4
127.0.0.1:6379> SUNION names nms ns
1) "zc003"
2) "zc007"
3) "zc002"
4) "zc001"
5) "zc004"
6) "zc000"
7) "zc006"
8) "zc005"
回傳所有集合并集,并保存為新值
O = A∪B∪C…
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SADD names zc001 zc002 zc003 zc004
(integer) 4
127.0.0.1:6379> SADD nms zc004 zc005 zc006 zc007
(integer) 4
127.0.0.1:6379> SADD ns zc000 zc001 zc002 zc005
(integer) 4
127.0.0.1:6379> SUNIONSTORE newnames names nms ns
(integer) 8
127.0.0.1:6379> SMEMBERS newnames
1) "zc003"
2) "zc007"
3) "zc002"
4) "zc001"
5) "zc004"
6) "zc000"
7) "zc006"
8) "zc005"
每次部分遍歷集合元素
127.0.0.1:6379> SADD names zc001 zc002 zc003 zhangchi001 zhangchi002 zhangchi003
(integer) 6
//從names中游標為0的地方開始每次查兩條
//在其中找到滿足zc*通配的記錄
127.0.0.1:6379> SSCAN names 0 match zc* count 2
1) "1" //回傳游標的位置
2) 1) "zc003"
//第二次繼續使用上次回傳的游標位置查詢
127.0.0.1:6379> SSCAN names 1 match zc* count 2
1) "0" //回傳0則遍歷結束
2) 1) "zc002"
2) "zc001"
4.哈希Hash
redis hash是一個String型別的鍵值對的映射表,hash特別適合用于存盤物件,
設定哈希表key(可以多個)中的欄位值為value,可以覆寫
HMSET用法和HSET完全一樣,HSET也可以設定多個值
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> HSET people name zhangchi age 18 //可以批量設定
(integer) 2
127.0.0.1:6379> HGETALL people //遍歷key中所有值
1) "name"
2) "zhangchi"
3) "age"
4) "18"
127.0.0.1:6379> HSET people name zhangchi001 //重復設定會覆寫
(integer) 0
127.0.0.1:6379> HGETALL people
1) "name"
2) "zhangchi001"
3) "age"
4) "18"
只有當欄位不存在時、設定hash表的值
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> HSET people name zhangchi
(integer) 1
//設定已經存在的欄位 會失敗回傳0
127.0.0.1:6379> HSETNX people name zhangchi001
(integer) 0
127.0.0.1:6379> HSETNX people age 18
(integer) 1
127.0.0.1:6379> HGETALL people
1) "name"
2) "zhangchi"
3) "age"
4) "18"
查看哈希表key中是否包含某個欄位
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> HSET people name zhangchi age 18
(integer) 2
127.0.0.1:6379> HEXISTS people name
(integer) 1
127.0.0.1:6379> HEXISTS people gender
(integer) 0
獲取哈希表中指定欄位的值
127.0.0.1:6379> HGET people name
"zhangchi"
127.0.0.1:6379> HGET people gender
(nil) //不存在的話回傳nil
獲取多個指定欄位的值
127.0.0.1:6379> HMGET people name gender age
1) "zhangchi"
2) (nil)
3) "18"
獲取在哈希表key中所有的的欄位和值
127.0.0.1:6379> HGETALL people
1) "name"
2) "zhangchi"
3) "age"
4) "18"
獲取哈希表中欄位的數量
127.0.0.1:6379> HLEN people
(integer) 2
獲取哈希表key中所有欄位
127.0.0.1:6379> HKEYS people
1) "name"
2) "age"
獲取hash表中所有的值
127.0.0.1:6379> HVALS people
1) "zhangchi"
2) "18"
洗掉多個欄位
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> HMSET people name zhangchi age 18 gender man
OK
127.0.0.1:6379> HDEL people age gender
(integer) 2
127.0.0.1:6379> HGETALL people
1) "name"
2) "zhangchi"
為哈希表某個欄位進行增量(整數)并回傳結果
127.0.0.1:6379> HSET people name zhangchi age 18
(integer) 2
127.0.0.1:6379> HINCRBY people age 2
(integer) 20 //回傳增量完成的結果
127.0.0.1:6379> HGETALL people
1) "name"
2) "zhangchi"
3) "age"
4) "20"
為哈希表某個欄位進行增量(小數)并回傳結果
127.0.0.1:6379> HSET people name zhangchi account 200.05
(integer) 2
127.0.0.1:6379> HINCRBYFLOAT people account 0.5
"200.55" //回傳增量完成的結果
127.0.0.1:6379> HGETALL people
1) "name"
2) "zhangchi"
3) "account"
4) "200.55"
由上面的操作可以看出hash更適合存盤物件,String適合存盤字串,
5.有序集合Zset
Zset和Set都是key-value都是String型別的字串,不同點在于每個元素都有一個double型別的分數score關聯,通過這個分數去排序,(集合元素是唯一的,但分數可以重復)
添加元素
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name zhangchi001 0.1 zhangchi002 0.2
獲取集合成員數
127.0.0.1:6379> ZCARD name
(integer) 2
獲取指定分數區間范圍內集合數量
127.0.0.1:6379> ZCOUNT name 0 0.1
(integer) 1
127.0.0.1:6379> ZCOUNT name 0 0.2
(integer) 2
對指定成員的分數加上增量n
//zhangchi001分數score上新增0.1個分量
127.0.0.1:6379> ZINCRBY name 0.1 zhangchi001
"0.20000000000000001" //因為精度損失問題
回傳有序集合中成員的分數值score
127.0.0.1:6379> ZSCORE name zhangchi001
"0.20000000000000001"
回傳有序集合中指定元素的索引(下標)
127.0.0.1:6379> ZRANK name zhangchi001
(integer) 0
127.0.0.1:6379> ZRANK name zhangchi002
(integer) 1
通過索引回傳指定取件范圍內成員
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
127.0.0.1:6379> ZRANGE name 0 -1// -1是倒數第一的意思
1) "zc001"
2) "zc002"
3) "zc003"
4) "zc004"
127.0.0.1:6379> ZRANGE name 0 2 //下標0-2
1) "zc001"
2) "zc002"
3) "zc003"
通過字典取件進行回傳
ZRANGEBYLEX key min max [LIMIT offset count]
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
//大于zc002 小于zc005 從下標為2開始取2條
127.0.0.1:6379> ZRANGEBYLEX name [zc002 [zc005 LIMIT 1 2
1) "zc003"
2) "zc004"
// - +表示最小和最大值
127.0.0.1:6379> ZRANGEBYLEX name - + LIMIT 1 2
1) "zc002"
2) "zc003"
通過分數條件查詢回傳指定區間的成員
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
//大于等于0.2小于等于0.5的記錄
127.0.0.1:6379> ZRANGEBYSCORE name 0.2 0.5
1) "zc002"
2) "zc003"
3) "zc004"
//大于0.2 小于0.5的記錄
127.0.0.1:6379> ZRANGEBYSCORE name (0.2 (0.5
1) "zc003"
2) "zc004"
//顯示分數負無窮到正無窮(即所有)的資料
127.0.0.1:6379> ZRANGEBYSCORE name -inf +inf
1) "zc001"
2) "zc002"
3) "zc003"
4) "zc004"
//從滿足情況的元素中 查詢下標為2開始的兩條記錄
127.0.0.1:6379> ZRANGEBYSCORE name -inf +inf LIMIT 2 2
1) "zc003"
2) "zc004"
在Zset中計算指定字典范圍內成員數量
127.0.0.1:6379> ZLEXCOUNT name - + //查所有
(integer) 5
//[zc002,zc005]
127.0.0.1:6379> ZLEXCOUNT name [zc002 [zc005
(integer) 4
移除成員
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
127.0.0.1:6379> ZREM name zc001 zc002
(integer) 2
127.0.0.1:6379> ZRANGE name 0 -1
1) "zc003"
2) "zc004"
移除字典區間范圍內的值
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
127.0.0.1:6379> ZREMRANGEBYLEX name - + //移除所有
(integer) 4
127.0.0.1:6379> ZRANGE name 0 -1
(empty list or set)
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
//移除zc001到zc003之間的資料
127.0.0.1:6379> ZREMRANGEBYLEX name [zc001 [zc003
(integer) 3
127.0.0.1:6379> ZRANGE name 0 -1
1) "zc004"
移除集合中排名區間(下標范圍)的所有成員
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
127.0.0.1:6379> ZREMRANGEBYRANK name 0 2
(integer) 3
127.0.0.1:6379> ZRANGE name 0 -1
1) "zc004"
移除指定分數范圍內的值
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
127.0.0.1:6379> ZREMRANGEBYSCORE name 0.2 0.3
(integer) 2
127.0.0.1:6379> ZRANGE name 0 -1
1) "zc001"
2) "zc004"
回傳集合范圍內的成員 通過索引下標 分數從高到低
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.2 zc003 0.1 zc004
(integer) 4
127.0.0.1:6379> ZREVRANGE name 0 -1
1) "zc003"
2) "zc002"
3) "zc004"
4) "zc001"
回傳指定分數區間范圍內的成員 分數從高到低排序
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.2 zc003 0.1 zc004
127.0.0.1:6379> ZREVRANGEBYSCORE name 0.2 0.1
1) "zc003"
2) "zc002"
3) "zc004"
4) "zc001"
回傳指定區間范圍內成員,按字典倒序
127.0.0.1:6379> ZREVRANGEBYLEX name [zc002 [zc001
1) "zc002"
2) "zc004"
3) "zc001"
回傳集合中元素排名 按照分數值從大到小
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
127.0.0.1:6379> ZREVRANK name zc003
(integer) 1 //從高到低下標1
127.0.0.1:6379> ZREVRANK name zc002
(integer) 2 //從高到低下標2
計算一個、多個有序集合的交集 將結果存盤在新的key中
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 1 zhangchi001 2 zhangchi002
(integer) 2
127.0.0.1:6379> ZADD nm 2 zhangchi003 4 zhangchi004 5 zhangchi002
(integer) 3
//newns是新集合名 2是運算的集合數
127.0.0.1:6379> ZINTERSTORE newns 2 name nm
(integer) 1
127.0.0.1:6379> ZRANGE newns 0 -1 WITHSCORES
1) "zhangchi002"
2) "7" //分數值為兩個集合中該項分數自核
計算一個、多個有序集合的并集 將結果存盤在新的key中
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 1 zhangchi001 2 zhangchi002
(integer) 2
127.0.0.1:6379> ZADD nm 2 zhangchi003 4 zhangchi004 5 zhangchi002
(integer) 3
127.0.0.1:6379> ZUNIONSTORE newns 2 name nm
(integer) 4 //新集合個數
127.0.0.1:6379> ZRANGE newns 0 -1 WITHSCORES
1) "zhangchi001"
2) "1"
3) "zhangchi003"
4) "2"
5) "zhangchi004"
6) "4"
7) "zhangchi002"
8) "7"
迭代集合中元素(條件分頁查詢)
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> ZADD name 0.1 zc001 0.2 zc002 0.3 zc003 0.4 zc004
(integer) 4
127.0.0.1:6379> ZSCAN name 0 MATCH zc*
1) "0" //下一次的游標 如果為0 表示結束
2) 1) "zc001"
2) "0.10000000000000001"
3) "zc002"
4) "0.20000000000000001"
5) "zc003"
6) "0.29999999999999999"
7) "zc004"
8) "0.40000000000000002"
//!!!這里COUNT不會生效 因為scan
127.0.0.1:6379> ZSCAN name 0 MATCH zc* COUNT 2
1) "0"
2) 1) "zc001"
2) "0.10000000000000001"
3) "zc002"
4) "0.20000000000000001"
5) "zc003"
6) "0.29999999999999999"
7) "zc004"
8) "0.40000000000000002"
四、三種特殊資料型別
redis除了五種基本資料型別外,還有三種特殊資料型別(基本不常用)
Geospatial(地理位置)、Hyperloglog(基數統計)、BitMaps(位圖)
Geospatial(地理位置):一般做附近的人
Hyperloglog(基數統計):特定情況下訪問量的統計
BitMaps(位圖):實作了直接操作位,一般試用于統計每榷訓躍用戶量
五、事務
redis單條命令是保證原子性的,但是redis事務不保證原子性
Redis 事務的本質是一組命令的集合,事務支持一次執行多個命令,一個事務中所有命令都會被序列化,在事務執行程序,會按照順序串行化執行佇列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中,
總結說:redis事務就是一次性、順序性、排他性的執行一個佇列中的一系列命令,
開啟事務:multi
命令入隊:
執行命令:exec
1.redis沒有事務隔離級別的概念
批量操作的命令在命令入隊的時候、執行命令exec之前,命令不會被真實執行,直到exec時候才會被順序執行
2.redis不保證原子性
redis的單條命令是保證原子性的(沒啥實際意義、肯定是對的),但是事務不保證原子性(每條命令執行失敗不影響別的命令的繼續執行)
3.redis事務的三個階段
開啟事務:MULTI
命令入隊:QUEUED
執行命令:EXEC
4.示例
正常執行
127.0.0.1:6379> MULTI //開啟事務
OK
127.0.0.1:6379> SET name zhangchi //設定key
QUEUED //入隊
127.0.0.1:6379> SET age 18 //設定key
QUEUED
127.0.0.1:6379> GET name //獲取value
QUEUED
127.0.0.1:6379> GET age //獲取value
QUEUED
127.0.0.1:6379> KEYS * //查詢所有key
QUEUED
127.0.0.1:6379> EXEC //執行
1) OK
2) OK
3) "zhangchi"
4) "18"
5) 1) "age"
2) "name"
取消事務
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET name zhangchi
QUEUED
127.0.0.1:6379> SET age 18
QUEUED
127.0.0.1:6379> DISCARD //取消事務
OK
127.0.0.1:6379> EXEC //執行事務
(error) ERR EXEC without MULTI //沒有事務可被執行
127.0.0.1:6379> DISCARD //取消事務
(error) ERR DISCARD without MULTI //沒有事務可被取消
127.0.0.1:6379> GET name
(nil)
語法錯誤
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET name zhangchi
QUEUED
127.0.0.1:6379> SETAAA BBB CCC //錯誤的語法會直接報錯不能執行事務
(error) ERR unknown command `SETAAA`, with args beginning with: `BBB`, `CCC`,
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
代碼邏輯錯誤(運行時例外),其他命令可以正常執行,所以不保證事務原子性
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET name zhangchi
QUEUED
127.0.0.1:6379> SET age 18
QUEUED
127.0.0.1:6379> INCR age
QUEUED
127.0.0.1:6379> INCR name //對字串增量是運行時例外
QUEUED
127.0.0.1:6379> GET age
QUEUED
127.0.0.1:6379> GET name
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) (integer) 19
//此處拋例外,其他位置陳述句不報錯,正常執行
4) (error) ERR value is not an integer or out of range
5) "19"
6) "zhangchi"
監控
–正常
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> SET name zhangchi
OK
127.0.0.1:6379> SET age 18
OK
127.0.0.1:6379> WATCH name age //監控name age
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECR age
QUEUED
127.0.0.1:6379> SET name zc
QUEUED
127.0.0.1:6379> EXEC //name age沒有被修改 則事務執行成功(樂觀鎖)
1) (integer) 17
2) OK
127.0.0.1:6379> MGET name age
1) "zc"
2) "17"
–非正常,監控值中途被修改了
--視窗1
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> MSET name zhangchi age 18
OK
127.0.0.1:6379> WATCH name age //監控name age
OK
127.0.0.1:6379> SET name zc001 //修改name
OK
--視窗2
127.0.0.1:6379> SET name zc
OK
--視窗1
127.0.0.1:6379> EXEC
(error) ERR EXEC without MULTI //name被中途修改了 事務拋例外結束
127.0.0.1:6379> MGET name age
1) "zc" //name被視窗2修改
2) "18"
由此可見 redis的監控機制使用的是樂觀鎖
每次提交執行exec都會被自動釋放鎖,不論成功與否
六、持久化-RDB
RDB:Redis Databases
在指定時間間隔后,將記憶體的資料集以快照的方式寫入資料庫;在恢復資料的時候,直接讀取快照檔案進行恢復
簡單來說就是定時創建快照對資料備份
1.作業原理
在redis進行RDB的時候,redis主執行緒不會進行io操作的,主執行緒會開啟fork一個子執行緒來進行操作,同時會默認生成一個dump.rdb的二進制檔案中,
2.觸發機制
1、滿足redis.conf中配置的save引數規則(多長時間有多少個key被修改了等等)
2、FLUSHALL時候
3、退出redis
注意:如果是kill -9殺死行程 不會備份
save的時候會阻塞主執行緒(同步)
解決該問題使用bgsave(異步,需要多開一個執行緒,消耗記憶體)
3.優缺點
優點:
1、適合大規模的資料恢復
2、對資料的完整性要求不高
缺點:
1、有時間間隔,可能會丟失資料
2、fork行程時候創建快斬訓占用一定的記憶體空間
七、持久化-AOF
1.作業原理
AOF:Append Only File
以日志的形式記錄下所有的寫操作,只允許追加文夾,不允許修改,redis會記錄下所有的寫操作指令,在宕機恢復的時候從前到后執行所有的的操作,
如果需要開啟該功能的話
appendonly no //改為yes開啟aof
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof" //默認檔案名
# appendfsync always //每次修改都會同步緩沖區命令 消耗性能
appendfsync everysec //每一秒執行一次同步緩沖區命令 可能丟失一秒的資料
# appendfsync no //由系統決定什么時候同步緩沖區命令 效率最高
2.優缺點
優點:
1、每次修改都會同步檔案,檔案的完整性更好
2、每次同步都是append的模式,不用消耗磁盤尋址能力的所占用的空間
3、適合災難性的誤洗掉進行緊急恢復
缺點:
1、相對于檔案數aof比rdb更多,修復的速度更慢
2、aof的運行效率也比rdb慢
八、Redis發布訂閱(基本不用)
Redis其實也可以做訊息中間件使用
Redis提供了發布訂閱模式
--訂閱端
127.0.0.1:6379> SUBSCRIBE zhangchi //訂閱一個zhangchi頻道
Reading messages... (press Ctrl-C to quit) //等待接收訊息
1) "subscribe" //訂閱成功
2) "zhangchi" //頻道名稱
3) (integer) 1
1) "message" //收到訊息
2) "zhangchi" //來自的頻道
3) "hahaha" //訊息內容
1) "message"
2) "zhangchi"
3) "hehehe"
--發布端
127.0.0.1:6379> PUBLISH zhangchi hahaha //發布hahaha到zhangchi頻道
(integer) 1
127.0.0.1:6379> PUBLISH zhangchi hehehe
(integer) 1
--查看活躍的頻道
127.0.0.1:6379> PUBSUB channels
1) "zhangchi"
127.0.0.1:6379> PUBSUB channels //如果把訂閱者都關閉
(empty list or set)
九、Redis主從復制
十、Redis哨兵模式
以上兩個會新開一個文章,到時候鏈接進來
十一、快取穿透與雪崩
1.快取穿透(查不到)
在用戶請求資料時候,會現在redis中查找,如果查找不到再去資料庫中查找,并快取進資料庫,數量較少可能不會有問題,但是如果遇到秒殺場景所有快取都查不到時候,壓力會全部轉移到資料庫上,這時候就可能造成資料庫崩潰,
解決方案:
1、布隆過濾器
對所有的可能查詢的引數以Hash的形式進行存盤,以便快速確定是否有結果,在控制層進行校驗,不通過的直接回傳,減輕系統壓力

2、快取空物件
一次請求如果在redis和資料庫中都沒找到,就快取一個空物件回傳

缺陷:空物件也消耗空間、并且對業務的一致性有影響(會有資料庫實際存在,但是查出為空的情況)
2.快取擊穿(量太大,快取過期)
在快取過期的那一刻,有大量請求同時訪問一個key,瞬間擊穿到資料庫,造成一瞬間的請求壓力過大
微博熱點經常有這種情況
解決方案:
1、設定熱點資料永不過期
可能會有redis滿了 會自動清理的風險
2、加互斥鎖(分布式鎖)
快取中沒有的話 只放行一個請求去查資料庫 并快取進redis
3.快取雪崩
跟快取擊穿稍微有點像,雪崩是指同一時間有大量的key同時失效,造成資料庫瞬間的壓力過大,引起雪崩

解決方案:
1、redis高可用(集群搭建)
2、限流降級
類似擊穿中加互斥鎖,限制訪問資料庫的數量
3、資料遇熱
專案部署前,先把所有的資料事先訪問一遍,預先加載到redis中
4、將快取失效時間盡可能設定均勻點
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/261354.html
標籤:其他
