redis的基本數據類型
- 1、redis
- 1.1、數據庫分類
- 1.2、NoSQL分類
- 1.3、redis簡介
- 1.4、redis應用
- 1.5、如何學習redis
- 2、redis的安裝
- 2.1、Windows安裝
- 2.2.1、客戶端redis管理工具
- 2.2、Linux安裝🔥
- 2.2.1、redis核心文件
- 2.2.2、啟動方式
- 2.2.3、redis桌面客戶端
- 1、redis命令行客戶端
- 2、圖形化桌面客戶端
- 3、數據類型
- 3.1、概況
- 3.2、String類型
- 3.2.1、常用的命令
- 3.2.2、非常用命令
- 3.2.3、應用場景
- 3.3、Hash類型
- 3.3.0、內部實現
- 3.3.1、常用的命令
- 3.3.2、應用場景
- 3.4、List類型
- 3.4.0、內部實現
- 3.4.1、常用的命令
- 3.4.2、非常用命令
- 3.4.3、應用場景
- 3.5、Set類型
- 3.5.0、內部實現
- 3.5.1、常用的命令
- 3.5.2、非常用命令
- 3.5.4、應用場景
- 3.6、Zset類型
- 3.6.1、內部實現
- 3.6.1、常用的命令
- 3.6.2、非常用命令
- 3.6.4、應用場景
- 4、Key的設計
- 4.1、唯一性
- 4.2、可讀性
- 4.3、時效性
- 4.4、靈活性
- 5、設置密碼
- 5.1、通過配置文件設置密碼
- 5.2、通過命令行設置密碼
- 5.3、更改密碼
- 5.4、取消密碼
- 4.4、靈活性
- 參考視頻:適合后端編程人員的Redis實戰教程、redis應用場景、分布式緩存、Session管理、面試相關
1、redis
1.1、數據庫分類
-
目前數據庫分:關系型數據庫與非關系型數據庫
-
常用的關系型數據庫: Oracle,MySQL,SqlServer,DB2
-
常用的非關系數據庫:Redis,MongoDB,ElasticSearch, Hbase,Neo4j
-
那啥是非關系數據庫呢?此處涉及到新名詞:NoSQL
-
NoSQL最常見的解釋是"non-relational", "Not Only SQL"也被很多人接受。NoSQL僅僅是一個概念,泛指非關系型的數據庫,區別于關系數據庫,它們不保證關系數據的ACID特性。
如商城網站中對商品數據頻繁查詢、對熱搜商品的排行統計、訂單超時問題、以及微信朋友圈音頻、視頻存儲等相關使用傳統的關系型數據庫實現就顯得非常復雜,雖然能實現相應功能但是在性能上卻不是那么樂觀。NoSQL這個技術門類的出現,更好的解決了這些問題,它告訴了世界不僅僅是sql。
1.2、NoSQL分類
分類 | 舉例 | 典型應用場景 | 數據模型 | 優點 | 缺點 |
---|---|---|---|---|---|
鍵值(key-value)存儲數據庫 | redis | 內容緩存,主要用于處理大量數據的高訪問負載,也用于一些日志系統等。 | 通常用HashTable來實現 | 查找速度快 | 數據無結構化 |
列存儲數據庫 | HBase | 分布式的文件系統 | 將同一列數據存在一起 | 查找速度塊,更容易進行分布式擴展 | 功能相對局限 |
文檔型數據庫 | MongoDB | 查詢性能不高,且缺乏統一的查詢語法 | |||
圖形數據庫 | Infinite Graph | 社交網絡,專注于構建關系圖譜 | 圖結構 | 利用圖數據結構相關算法 | 對整個圖進行計算才能得到需要的信息 |
1.3、redis簡介
redis是以key-value形式存儲,和傳統的關系型數據庫不一樣。不一定遵循傳統數據庫的一些基本要求。
優點:
- 對數據高并發讀寫(直接是內存中進行讀寫的)
- 對海量數據的高效率存儲和訪問
- 對數據的可拓展性和高可用性
- 單線程操作,每個操作都是原子操作,沒有并發相關問題
缺點:
- 無法做太復雜的關系數據庫模型
- redis(ACID處理非常簡單)
redis 定位是緩存,提高數據讀寫速度,減輕對數據庫存儲和訪問壓力。redis是一個內存型的數據庫
1.4、redis應用
-
任務隊列,如秒殺、搶購、購票排隊等
-
即時信息查詢,如各位排行榜、各類網站訪問統計、公交到站信息
-
為熱點數據加速查詢(主要場景),如熱點商品、熱點新聞
-
消息隊列、分布式鎖
1.5、如何學習redis
-
redis 在線入門 : http://try.redis.io/
-
redis 中文資料官網: http://www.redis.cn/
-
redis 中文教程:https://www.runoob.com/redis/redis-tutorial.html
-
redis官網:https://redis.io/download/
2、redis的安裝
2.1、Windows安裝
- windows版:https://github.com/microsoftarchive/redis/releases/tag/win-3.2.100
傻瓜式安裝,一直下一步就可以了,注意要添加到環境變量中
默認端口:
最大內存
測試是否成功:
win+r
輸入redis-cli
2.2.1、客戶端redis管理工具
AnotherRedisDesktopManager
工具可以用來可視化管理redis,可以理解為 MySQL的 Sqlyog、Navicat等管理工具。
- Github: GUI client], compatible with Linux, Windows, Mac. (github.com)
- Gitee:AnotherRedisDesktopManager 發行版 - Gitee.com
下載完成后安裝即可:
2.2、Linux安裝🔥
- 進入Linux官網下載最新穩定版本:https://redis.io/download/
-
將其上傳至 Linux 服務器目錄下
/www/server/redis
中,并進行解壓。我這里使用
wget
命令下載,和上述步驟作用一致
# 進入/www/server/redis目錄下載
wget https://github.com/redis/redis/archive/7.2.3.tar.gz
http://github.com/redis/redis/archive/7.2.3.tar.gz
# 解壓
tar -zxvf 7.2.3.tar.gz
- 進入到解壓目錄,執行編譯命令
# 進入到解壓目錄
cd redis-7.2.3/# 執行編譯命令
make
- 進行安裝
# 安裝,默認是安裝到 /usr/local/bin 目錄
make install
共安裝了三個組件:redis server服務器、redis-cli客戶端與一個性能測試工具 benchmark
- 新建一個系統服務文件:
vi /etc/systemd/system/redis.service
內容如下:
[Unit]
Description=redis-server
After=network.target[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /www/server/redis/redis-7.2.3/redis.conf
PrivateTmp=true[Install]
WantedBy=multi-user.target
- 進入
/www/server/redis/redis-7.2.3
,先拷貝redis.conf
,然后進行修改
# 拷貝
cp redis.conf redis.conf.back
修改redis.conf
的配置
# 允許訪問的地址,默認是127.0.0.1,會導致只能在本地訪問。修改為0.0.0.0則可以在任意IP訪問,生產環境不要設置為0.0.0.0
bind 0.0.0.0
# 守護進程,修改為yes后即可后臺運行
daemonize yes
- 然后重載系統服務
systemctl daemon-reload
- 現在,我們可以用下面這組命令來操作redis了:
# 啟動
systemctl start redis
# 停止
systemctl stop redis
# 重啟
systemctl restart redis
# 查看狀態
systemctl status redis
- 執行下面的命令,可以讓redis開機自啟:
systemctl enable redis
- 查看 redis 版本
# 查看服務端版本
redis-server -v# 查看客戶端版本
redis-cli -v
2.2.1、redis核心文件
在 /usr/local/bin
目錄中,可以看到如下文件:
redis-serve
: 服務器啟動命令redis-cli
: 命令行客戶端redis-benchmark
: redis 性能測試工具redis-check-aof
:AOF文件修復工具redis-check-dump
:RDB文件檢查工具(快照持久化文件)
通過echo $PATH
可以看到,/usr/local/bin
目錄是存在于該系統變量中的,這樣這些命令就可以在任意目錄中執行了,這就是為什么我們在任意目錄都可以直接使用redis-cli
進行命令行
2.2.2、啟動方式
- 方式一:前臺啟動,安裝完成后,在任意目錄輸入redis-server命令即可啟動Redis
redis-server
這種啟動屬于前臺啟動
,會阻塞整個會話窗口,窗口關閉或者按下CTRL + C
則Redis停止。不推薦使用。
-
方式二:指定配置文件啟動,如果要讓Redis以
后臺
方式啟動,則必須修改Redis配置文件,就在我們之前解壓的redis安裝包下(/www/server/redis/redis-7.2.3
),名字叫redis.conf
-
我們先將這個配置文件備份一份:
cp redis.conf redis.conf.back
-
然后修改redis.conf文件中的一些配置:
# 允許訪問的地址,默認是127.0.0.1,會導致只能在本地訪問。修改為0.0.0.0則可以在任意IP訪問,生產環境不要設置為0.0.0.0 bind 0.0.0.0 # 守護進程,修改為yes后即可后臺運行 daemonize yes # 密碼,設置后訪問Redis必須輸入密碼 requirepass 1234
-
Redis的其它常見配置:
# 監聽的端口 port 6379 # 工作目錄,默認是當前目錄,也就是運行redis-server時的命令,日志.持久化等文件會保存在這個目錄 dir . # 數據庫數量,設置為1,代表只使用1個庫,默認有16個庫,編號0~15 databases 1 # 設置redis能夠使用的最大內存 maxmemory 512mb # 日志文件,默認為空,不記錄日志,可以指定日志文件名 logfile "redis.log"
-
啟動Redis:
# 進入redis安裝目錄 cd /www/server/redis/redis-7.2.3 # 啟動 redis-server redis.conf
-
停止redis
# 利用redis-cli來執行 shutdown 命令,即可停止 Redis 服務, # 因為之前配置了密碼,因此需要通過 -u 來指定密碼 redis-cli -u 1234 shutdown
-
-
方式三是開機自啟,已經在2.2目錄進行了設置
當給
redis.conf
設置了密碼requirepass 1234
,則啟動時需要auth 1234
2.2.3、redis桌面客戶端
1、redis命令行客戶端
Redis安裝完成后就自帶了命令行客戶端:redis-cli,使用方式如下:
redis-cli [options] [commonds]
其中常見的options有:
-h 127.0.0.1
:指定要連接的redis節點的IP地址,默認是127.0.0.1-p 6379
:指定要連接的redis節點的端口,默認是6379-a 1234
:指定redis的訪問密碼
其中的commonds就是Redis的操作命令,例如:
ping
:與redis服務端做心跳測試,服務端正常會返回pong
2、圖形化桌面客戶端
-
AnotherRedisDesktopManager
-
進去下載 exe 文件即可
-
使用教程:https://blog.csdn.net/zsewer/article/details/129325846
注意:在連接的時候請確保服務器的防火墻端口打開
6379
,否則會連接不上
3、數據類型
3.1、概況
Redis支持的存儲數據類型有很多:
-
常用:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)
-
不常用:HyperLogLog,Bitmap(位圖),Bloom Filter(布隆過濾器),Geospatial(地理位置) ,Module(模塊), Streams(流信息)
命令格式
類型命令 | key | value |
---|---|---|
set | name | zhangsan |
操作建議
-
Redis操作有點類似Java的Map集合,都是key-value形式存儲數據,在學習過程中,可以進行類比。
-
另外Redis中的key大部分為String類型,value值根據緩存數據結構可以選用:string,hash,list,set,zset等類型。
注意:下面講的各種類型,表述的是緩存數據的value類型。
3.2、String類型
String類型包含多種類型的特殊類型,并且是二進制安全的,其值可以是數值,可以是字符串,也可以是二進制數據。
3.2.1、常用的命令
命令格式 | 功能 | 案例 | 說明 |
---|---|---|---|
set key value | 將key-value緩存redis中 | set name qxl | 設置name字段為qxl |
get key | 從redis中獲取key對應value值 | get name | 獲取name字段對應的value |
incr key | 將key對應value值 + 1 | incr age | 給age字段+1 |
decr key | 將key對應value值-1 | decr age | 給age字段-1 |
setex key seconds value | 將key-value緩存到redis中,seconds 秒后失效 | setex sex 10 man | 將sex字段設置為10s的man |
ttl key | 查看key存活時間 | ttl sex | 查看sex字段對應的 value 存活時間 |
del key | 從redis中刪除key | del name | 刪除name字段 |
setnx key value | 如果key已經存,不做任何操作,如果key不存,直接添加 | setnx name xiaofei |
普通字符串的基本操作:
# 設置 key-value 類型的值
> SET name lin
OK# 根據 key 獲得對應的 value
> GET name
"lin"# 判斷某個 key 是否存在
> EXISTS name
(integer) 1# 返回 key 所儲存的字符串值的長度
> STRLEN name
(integer) 3# 刪除某個 key 對應的值
> DEL name
(integer) 1
3.2.2、非常用命令
命令格式 | 功能 | 案例 |
---|---|---|
incrby key increment | 給key對應值加increment | incrby age 10 |
mset k1 v1 k2 v2… | 批量添加k1v1 k2v2 key value對 | mset name dafei age 18 |
mget k1 k2… | 批量獲取k1, k2的值 | mget name age |
append key value | 在key對應的value值中拼+value | append name yes |
setrange key offset value | 修改key對應的value值,替換為指定value,沖offset索引位置開始 | setrange name 2 xx |
批量設置:
# 批量設置 key-value 類型的值
> MSET key1 value1 key2 value2
OK# 批量獲取多個 key 對應的 value
> MGET key1 key2
1) "value1"
2) "value2"
計數器(字符串的內容為整數的時候可以使用):
# 設置 key-value 類型的值
> SET number 0
OK# 將 key 中儲存的數字值增一
> INCR number
(integer) 1# 將key中存儲的數字值加 10
> INCRBY number 10
(integer) 11# 將 key 中儲存的數字值減一
> DECR number
(integer) 10# 將key中存儲的數字值鍵 10
> DECRBY number 10
(integer) 0
過期(默認為永不過期):
# 設置 key 在 60 秒后過期(該方法是針對已經存在的key設置過期時間)
> EXPIRE name 60
(integer) 1
# 查看數據還有多久過期
> TTL name
(integer) 51#設置 key-value 類型的值,并設置該key的過期時間為 60 秒
> SET key value EX 60
OK
> SETEX key 60 value
OK
不存在就插入:
# 不存在就插入(not exists)
>SETNX key value
(integer) 1
3.2.3、應用場景
-
緩存對象:使用 String 來緩存對象有兩種方式:
- 直接緩存整個對象的 JSON,命令例子:
SET user:1 '{"name":"xiaolin", "age":18}'
。 - 采用將 key 進行分離為 user:ID:屬性,采用 MSET 存儲,用 MGET 獲取各屬性值,命令例子:
MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20
。
- 直接緩存整個對象的 JSON,命令例子:
-
主頁高頻訪問信息顯示控制,例如新浪微博大V主頁顯示粉絲數與微博數量。這就是常規計數,計算訪問次數、點贊次數、轉發次數等。
-
共享session:
-
通常我們在開發后臺管理系統時,會使用 Session 來保存用戶的會話(登錄)狀態,這些 Session 信息會被保存在服務器端,但這只適用于單系統應用,如果是分布式系統此模式將不再適用。
-
例如用戶一的 Session 信息被存儲在服務器一,但第二次訪問時用戶一被分配到服務器二,這個時候服務器并沒有用戶一的 Session 信息,就會出現需要重復登錄的問題,問題在于分布式系統每次會把請求隨機分配到不同的服務器。
-
- 出于負載均衡的考慮,分布式服務會將用戶信息的訪問均衡到不同服務器上,用戶刷新一次訪問可能會需要重新登錄,為避免這個問題可以用redis將用戶session集中管理, 在這種模式下只要保證redis的高可用和擴展性的,每次獲取用戶更新或查詢登錄信息都直接從redis中集中獲取。
3.3、Hash類型
Hash 是一個鍵值對(key - value)集合,其中 value 的形式如: value=[{field1,value1},...{fieldN,valueN}]
。Hash類型特別適合存儲對象:
類似Java中:Map<String, Map<String, ?>> map
3.3.0、內部實現
Hash 類型的底層數據結構是由壓縮列表或哈希表實現的:
- 如果哈希類型元素個數小于
512
個,所有值小于64
字節的話,Redis 會使用壓縮列表作為 Hash 類型的底層數據結構; - 如果哈希類型元素不滿足上面條件,Redis 會使用哈希表作為 Hash 類型的 底層數據結構
在 Redis 7.0 中,壓縮列表數據結構已經廢棄了,交由 listpack 數據結構來實現了。
3.3.1、常用的命令
命令格式 | 功能 | 案例 | 說明 |
---|---|---|---|
hset key field value | 將field value對緩存到redis中hash中,鍵值為key | hset user name dafei | 給user中的name字段設置為dafei |
hget key field | 從key對應hash列表中獲取field字段 | hget user name | 獲取user中的name字段 |
hexists key field | 判斷key對應的hash列表是否存在 field字段 | hexists user age | 判斷user中是否存在age字段 |
hdel key field | 刪除key對應hash列表中field字段 | hdel user age | 刪除user中的age字段 |
hincrby key field increment | 給key對應hash列表中field字段 + increment | hincrby user age 10 | 給user中的age字段+10 |
hlen key | 查看key對應的hash列表field的數量 | hlen user | 查看user中的所有 key |
hkeys key | 獲取key對應的hash列表所有的field值 | hkeys user | 獲取user中的所有 key |
hvals key | 獲取key對應的hash列表所有的field對應的value值 | hvals user | 獲取user中的所有value |
hgetall key | 獲取key對應的hash列表中所有的field及其對應的value值 | hgetall user | 獲取user中的所有 key 和 value |
# 存儲一個哈希表key的鍵值
HSET key field value
# 獲取哈希表key對應的field鍵值
HGET key field# 在一個哈希表key中存儲多個鍵值對
HMSET key field value [field value...]
# 批量獲取哈希表key中多個field鍵值
HMGET key field [field ...]
# 刪除哈希表key中的field鍵值
HDEL key field [field ...] # 返回哈希表key中field的數量
HLEN key
# 返回哈希表key中所有的鍵值
HGETALL key # 為哈希表key中field鍵的值加上增量n
HINCRBY key field n
Hash類型數據操作的注意事項:
- Hash類型下的 value 只能存儲字符串,不允許存儲其他數據類型
- Hash設計的初衷不是為了存儲大量對象的,切記不可濫用。
3.3.2、應用場景
-
緩存對象:Hash 類型的 (key,field, value) 的結構與對象的(對象id, 屬性, 值)的結構相似,也可以用來存儲對象。我們以用戶信息為例,它在關系型數據庫中的結構是這樣的:
uid name age 1 Tom 15 2 Jerry 13 我們可以使用如下命令,將用戶對象的信息存儲到 Hash 類型:
# 存儲一個哈希表uid:1的鍵值 > HMSET uid:1 name Tom age 15 2 # 存儲一個哈希表uid:2的鍵值 > HMSET uid:2 name Jerry age 13 2 # 獲取哈希表用戶id為1中所有的鍵值 > HGETALL uid:1 1) "name" 2) "Tom" 3) "age" 4) "15
一般對象用 String + Json 存儲,對象中某些頻繁變化的屬性可以考慮抽出來用 Hash 類型存儲。
-
電商網站購物車設計
-
以客戶id作為key,每位客戶創建一個hash存儲結構存儲對應的購物車信息。將商品編號作為field,購買數量作為value進行存儲
key value id {
name: dafei
field:001
value:3
} -
添加購物車:追加全新的field與value
-
瀏覽購物車:遍歷hash
-
更改購物車數量:自增/自減,設置value值
-
刪除購物車商品:刪除field
-
清空購物車:刪除key
-
3.4、List類型
- List類型是一個鏈表結構的集合,其主要功能有push、pop、獲取元素等。
- 類似Java中:Map<String, List> map
3.4.0、內部實現
- 如果列表的元素個數小于
512
個,列表每個元素的值都小于64
字節,Redis 會使用壓縮列表作為 List 類型的底層數據結構; - 如果列表的元素不滿足上面的條件,Redis 會使用雙向鏈表作為 List 類型的底層數據結構
但是在 Redis 3.2 版本之后,List 數據類型底層數據結構就只由 quicklist 實現了,替代了雙向鏈表和壓縮列表
3.4.1、常用的命令
命令格式 | 功能 | 案例 | 說明 |
---|---|---|---|
rpush key value | 從右邊往key集合中添加value值 | rpush hobby java | 從右邊向 hobby 集合中添加 java 字段 |
lrange key start stop | 從左邊開始列表key集合,從start位置開始,stop位置結束 | lrange hobby 0 3 lrange hobby 0 -1 | 從左邊開始羅列 hobby 集合下標 0-3 的字段 從左邊開始羅列 hobby 集合下所有字段 |
lpush key value | 從左邊往key集合中添加value值 | lpush hobby c++ | 從左邊向 hobby 集合中添加 c++ 字段 |
lpop key | 彈出key集合中最左邊的數據 | lpop hobby | 彈出 hobby 集合中最左邊的數據 |
rpop key | 彈出key集合中最右邊的數據 | rpop hobby | 彈出 hobby 集合中最右邊的數據 |
llen key | 獲取列表長度 | llen hooby | 獲取 hobby 集合的長度 |
# 將一個或多個值value插入到key列表的表頭(最左邊),最后的值在最前面
LPUSH key value [value ...]
# 將一個或多個值value插入到key列表的表尾(最右邊)
RPUSH key value [value ...]
# 移除并返回key列表的頭元素
LPOP key
# 移除并返回key列表的尾元素
RPOP key # 返回列表key中指定區間內的元素,區間以偏移量start和stop指定,從0開始
LRANGE key start stop# 從key列表表頭彈出一個元素,沒有就阻塞timeout秒,如果timeout=0則一直阻塞
BLPOP key [key ...] timeout
# 從key列表表尾彈出一個元素,沒有就阻塞timeout秒,如果timeout=0則一直阻塞
BRPOP key [key ...] timeout
3.4.2、非常用命令
命令格式 | 功能 | 案例 |
---|---|---|
linsert key before pivot value | 操作key集合,在pivot值之前插入value | linsert hobby before java c# |
linsert key after pivot value | 操作key集合,在pivot值之后插入value | linsert hobby after java c# |
lset key index value | 操作key集合,更新索引index位置值為value | lset hobby 1 go |
lrem key count value | 操作key集合,刪除 count個 value值 | lrem hobby 3 go |
ltrim key start stop | 操作key集合,從start到stop截取自列表 | ltrim hobby 2 4 |
lindex key index | 操作key集合,獲取索引為index位置的數據 | lindex hobby 1 |
3.4.3、應用場景
- 用戶收藏文章列表:
key | value |
---|---|
user_favor_article_list | [aid1, aid2, aid3…] |
- 消息隊列:小林coding
3.5、Set類型
Set 類型是一個無序并唯一的鍵值集合,它的存儲順序不會按照插入的先后順序進行存儲。
Set 類型和 List 類型的區別如下:
- List 可以存儲重復元素,Set 只能存儲非重復元素;
- List 是按照元素的先后順序存儲元素的,而 Set 則是無序方式存儲元素的。
3.5.0、內部實現
Set 類型的底層數據結構是由哈希表或整數集合實現的:
- 如果集合中的元素都是整數且元素個數小于
512
(默認值,set-maxintset-entries
配置)個,Redis 會使用整數集合作為 Set 類型的底層數據結構; - 如果集合中的元素不滿足上面條件,則 Redis 使用哈希表作為 Set 類型的底層數據結構。
3.5.1、常用的命令
命令格式 | 功能 | 案例 | 說明 |
---|---|---|---|
sadd key members […] | 往key 集合中添加member元素 | sadd myset a b c | 給集合 myset 添加 a b c 元素 |
smembers key | 遍歷key集合中所有的元素 | smembers myset | 遍歷集合 myset |
srem key members […] | 刪除key集合中members元素 | srem myset a | 刪除myset集合中的元素a |
spop key count | 從key集合中隨機彈出count個元素 | spop myset 1 |
# 往集合key中存入元素,元素存在則忽略,若key不存在則新建
SADD key member [member ...]
# 從集合key中刪除元素
SREM key member [member ...]
# 獲取集合key中所有元素
SMEMBERS key
# 獲取集合key中的元素個數
SCARD key# 判斷member元素是否存在于集合key中
SISMEMBER key member# 從集合key中隨機選出count個元素,元素不從key中刪除
SRANDMEMBER key [count]
# 從集合key中隨機選出count個元素,元素從key中刪除
SPOP key [count]
3.5.2、非常用命令
命令格式 | 功能 | 案例 |
---|---|---|
sdiff key1 key2 | 返回key1中特有的元素(差集) | sdiff key1 key2 |
sidiffstore dest key1 key2 | 返回key1中特有的元素,并將返回值緩存到dest集合中 | sidiffstore dest key1 key2 |
sinter key1 key2 | 返回key1跟key2集合的交集 | sinter key1 key2 |
sinterstore dest key1 key2 | 返回key1跟key2集合的交集,并將返回值緩存到dest集合中 | sinterstore dest key1 key2 |
sunion key1 key2 | 返回key1跟key2集合的并集 | sunion key1 key2 |
sunionstore dest key1 key2 | 返回key1跟key2集合的并集,并將返回值緩存到dest集合中 | sunionstore dest key1 key2 |
smove source destination member | 將source集合中member元素移動到destination集合中 | smove key1 key2 aa |
sismember key member | 判斷member元素是否在key集合中 | sismember key1 aa |
srandmember key count | 隨機獲取set集合中count 個元素 | srandmem |
# 交集運算
SINTER key [key ...]
# 將交集結果存入新集合destination中
SINTERSTORE destination key [key ...]# 并集運算
SUNION key [key ...]
# 將并集結果存入新集合destination中
SUNIONSTORE destination key [key ...]# 差集運算
SDIFF key [key ...]
# 將差集結果存入新集合destination中
SDIFFSTORE destination key [key ...]
3.5.4、應用場景
集合的主要幾個特性,無序、不可重復、支持并交差等操作。因此 Set 類型比較適合用來數據去重和保障數據的唯一性,還可以用來統計多個集合的交集、錯集和并集等,當我們存儲的數據是無序并且需要去重的情況下,比較適合使用集合類型進行存儲。
Set 的差集、并集和交集的計算復雜度較高,在數據量較大的情況下,如果直接執行這些計算,會導致 Redis 實例阻塞
在主從集群中,為了避免主庫因為 Set 做聚合計算(交集、差集、并集)時導致主庫被阻塞,我們可以選擇一個從庫完成聚合統計,或者把數據返回給客戶端,由客戶端來完成聚合統計。
-
點贊場景:Set 類型可以保證一個用戶只能點一個贊,這里舉例子一個場景,key 是文章id,value 是用戶id。
# uid:1 、uid:2、uid:3 三個用戶分別對 article:1 文章點贊了 # uid:1 用戶對文章 article:1 點贊 > SADD article:1 uid:1 (integer) 1 # uid:2 用戶對文章 article:1 點贊 > SADD article:1 uid:2 (integer) 1 # uid:3 用戶對文章 article:1 點贊 > SADD article:1 uid:3 (integer) 1
# uid:1 取消了對 article:1 文章點贊。 > SREM article:1 uid:1 (integer) 1# 獲取 article:1 文章所有點贊用戶 > SMEMBERS article:1 1) "uid:3" 2) "uid:2"# 獲取 article:1 文章的點贊用戶數量 > SCARD article:1 (integer) 2# 判斷用戶 uid:1 是否對文章 article:1 點贊了 > SISMEMBER article:1 uid:1 (integer) 0 # 返回0說明沒點贊,返回1則說明點贊了
-
共同關注:Set 類型支持交集運算,所以可以用來計算共同關注的好友、公眾號等
# key 可以是用戶id,value 則是已關注的公眾號的id。 # uid:1 用戶關注公眾號 id 為 5、6、7、8、9,uid:2 用戶關注公眾號 id 為 7、8、9、10、11# uid:1 用戶關注公眾號 id 為 5、6、7、8、9 > SADD uid:1 5 6 7 8 9 (integer) 5 # uid:2 用戶關注公眾號 id 為 7、8、9、10、11 > SADD uid:2 7 8 9 10 11 (integer) 5# 獲取共同關注 > SINTER uid:1 uid:2 1) "7" 2) "8" 3) "9"# 給 uid:2 推薦 uid:1 關注的公眾號 > SDIFF uid:1 uid:2 1) "5" 2) "6"# 驗證某個公眾號是否同時被 uid:1 或 uid:2 關注: > SISMEMBER uid:1 5 (integer) 1 # 返回0,說明關注了 > SISMEMBER uid:2 5 (integer) 0 # 返回0,說明沒關注
-
抽獎活動:存儲某活動中中獎的用戶名 ,Set 類型因為有去重功能,可以保證同一個用戶不會中獎兩次
# key為抽獎活動名,value為員工名稱,把所有員工名稱放入抽獎箱 >SADD lucky Tom Jerry John Sean Marry Lindy Sary Mark (integer) 5# 如果允許重復中獎,可以使用 SRANDMEMBER 命令 # 抽取 1 個一等獎: > SRANDMEMBER lucky 1 1) "Tom" # 抽取 2 個二等獎: > SRANDMEMBER lucky 2 1) "Mark" 2) "Jerry" # 抽取 3 個三等獎: > SRANDMEMBER lucky 3 1) "Sary" 2) "Tom" 3) "Jerry"
如果不允許重復中獎,可以使用 SPOP 命令
# 抽取一等獎1個 > SPOP lucky 1 1) "Sary" # 抽取二等獎2個 > SPOP lucky 2 1) "Jerry" 2) "Mark" # 抽取三等獎3個 > SPOP lucky 3 1) "John" 2) "Sean" 3) "Lindy"
3.6、Zset類型
- Zset 類型(有序集合類型)相比于 Set 類型多了一個排序屬性 score(分值),對于有序集合 ZSet 來說,每個存儲元素相當于有兩個值組成的,一個是有序集合的元素值,一個是排序值。
- 有序集合保留了集合不能有重復成員的特性(分值可以重復),但不同的是,有序集合中的元素可以排序。
3.6.1、內部實現
Zset 類型的底層數據結構是由壓縮列表或跳表實現的:
- 如果有序集合的元素個數小于
128
個,并且每個元素的值小于64
字節時,Redis 會使用壓縮列表作為 Zset 類型的底層數據結構; - 如果有序集合的元素不滿足上面的條件,Redis 會使用跳表作為 Zset 類型的底層數據結構;
在 Redis 7.0 中,壓縮列表數據結構已經廢棄了,交由 listpack 數據結構來實現了。
3.6.1、常用的命令
命令格式 | 功能 | 案例 | 說明 |
---|---|---|---|
zadd key score member | 往key集合中添加member元素,分數為score | zadd players 100 a | 向players集合添加a元素,分數為100 |
zincrby key increment member | 將key集合中的member元素 分數 + increment | zadd players 100 a | 向players集合的a元素分數+100 |
zrange key start stop [withscores] | 將key集合中的元素按分數升序排列 [顯式分數] | zrange players 0 -1 withscores | |
zrevrange key start stop [withscores] | 將key集合中的元素按分數降序排列 [顯式分數] | zrevrange players 0 -1 withscores | |
zrank key member | 返回member元素在key結合中的正序排名 | zrank players a | 返回players集合中a元素的正序排名 |
zrevrank key member | 返回member元素在key結合中的倒序排名 | zrevrank players a | |
zcard key | 返回key集合元素個數 | zcard players |
# 往有序集合key中加入帶分值元素
ZADD key score member [[score member]...]
# 往有序集合key中刪除元素
ZREM key member [member...]
# 返回有序集合key中元素member的分值
ZSCORE key member
# 返回有序集合key中元素個數
ZCARD key # 為有序集合key中元素member的分值加上increment
ZINCRBY key increment member # 正序獲取有序集合key從start下標到stop下標的元素
ZRANGE key start stop [WITHSCORES]
# 倒序獲取有序集合key從start下標到stop下標的元素
ZREVRANGE key start stop [WITHSCORES]# 返回有序集合中指定分數區間內的成員,分數由低到高排序。
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]# 返回指定成員區間內的成員,按字典正序排列, 分數必須相同。
ZRANGEBYLEX key min max [LIMIT offset count]
# 返回指定成員區間內的成員,按字典倒序排列, 分數必須相同
ZREVRANGEBYLEX key max min [LIMIT offset count]
Zset 運算操作(相比于 Set 類型,ZSet 類型沒有支持差集運算):
# 并集計算(相同元素分值相加),numberkeys一共多少個key,WEIGHTS每個key對應的分值乘積
ZUNIONSTORE destkey numberkeys key [key...]
# 交集計算(相同元素分值相加),numberkeys一共多少個key,WEIGHTS每個key對應的分值乘積
ZINTERSTORE destkey numberkeys key [key...]
3.6.2、非常用命令
命令格式 | 功能 | 案例 |
---|---|---|
zrangebyscore key min max [withscores] | 按[min, max) 分數范圍返回key集合中元素(正序) | zrangebyscore players 200 300 withscores |
zrevrangebyscore key min max [withscores] | 按[min, max) 分數范圍返回key集合中元素(倒序) | zrevrangebyscore players 200 300 withscores |
zrem key member | 刪除key集合中member元素與分數 | zrem players a |
zremrangebyscore key min max withscores | 按[min, max) 分數范圍刪除key集合中元素 | zremrangebyscore players 200 300 withscores |
zremrangebyrank key start stop | 刪除key集合正序排名落在[start, stop) 范圍元素 | zremrangebyrank players 10 20 |
zcount key min max | 按照分數范圍[min, max]統計key集合中元素個數 | zcount players 100 300 |
3.6.4、應用場景
? Zset 類型(Sorted Set,有序集合) 可以根據元素的權重來排序,我們可以自己來決定每個元素的權重值。比如說,我們可以根據元素插入 Sorted Set 的時間確定權重值,先插入的元素權重小,后插入的元素權重大。
? 在面對需要展示最新列表、排行榜等場景時,如果數據更新頻繁或者需要分頁顯示,可以優先考慮使用 Sorted Set。
-
排行榜:我們以博文點贊排名為例,小林發表了五篇博文,分別獲得贊為 200、40、100、50、150。
# arcticle:1 文章獲得了200個贊 > ZADD user:xiaolin:ranking 200 arcticle:1 (integer) 1 # arcticle:2 文章獲得了40個贊 > ZADD user:xiaolin:ranking 40 arcticle:2 (integer) 1 # arcticle:3 文章獲得了100個贊 > ZADD user:xiaolin:ranking 100 arcticle:3 (integer) 1 # arcticle:4 文章獲得了50個贊 > ZADD user:xiaolin:ranking 50 arcticle:4 (integer) 1 # arcticle:5 文章獲得了150個贊 > ZADD user:xiaolin:ranking 150 arcticle:5 (integer) 1
文章 arcticle:4 新增一個贊,可以使用 ZINCRBY 命令(為有序集合key中元素member的分值加上increment):
> ZINCRBY user:xiaolin:ranking 1 arcticle:4 "51"
查看某篇文章的贊數,可以使用 ZSCORE 命令(返回有序集合key中元素個數):
> ZSCORE user:xiaolin:ranking arcticle:4 "50"
獲取小林文章贊數最多的 3 篇文章,可以使用 ZREVRANGE 命令(倒序獲取有序集合 key 從start下標到stop下標的元素):
# WITHSCORES 表示把 score 也顯示出來 > ZREVRANGE user:xiaolin:ranking 0 2 WITHSCORES 1) "arcticle:1" 2) "200" 3) "arcticle:5" 4) "150" 5) "arcticle:3" 6) "100"
獲取小林 100 贊到 200 贊的文章,可以使用 ZRANGEBYSCORE 命令(返回有序集合中指定分數區間內的成員,分數由低到高排序):
> ZRANGEBYSCORE user:xiaolin:ranking 100 200 WITHSCORES 1) "arcticle:3" 2) "100" 3) "arcticle:5" 4) "150" 5) "arcticle:1" 6) "200"
4、Key的設計
Redis 的key 設計講究4個性:
4.1、唯一性
Redis 類似Map集合,key必須保證唯一,緩存同一個key時,后者會覆蓋前者,所以必須要求唯一,那如何保證唯一呢?最常用的方式:使用緩存數據的主鍵作為key。
比如:緩存員工信息
key | value |
---|---|
1 | 員工1 |
2 | 員工2 |
其中的1, 2 是員工的id
4.2、可讀性
可讀性是保證Redis的key能做到見名知意,上面的員工id1, 員工id2 雖說能保證key唯一,但可讀性非常差,維護key時,無法從1, 2中快速判斷該key對應value值。所以一一般在保證key唯一的前提下,給key加上前綴:
key | value |
---|---|
employee_info:id1 | 員工1 |
employee_info:id2 | 員工2 |
employee_info:id1
、 employee_info:id2
這樣子設計key,可讀性就好多了。
- 通用玩法:業務模塊名:業務邏輯含義:其他:value類型
key | value |
---|---|
employee :base.info:id1:hash | 員工對象信息 |
業務模塊名:表示該key屬于哪個功能模塊
業務邏輯含義段:這里可以使用 . 分開, 具體業務邏輯表示
- 比如:緩存員工權限:
employee:auth.permission:id1:set
員工權限集合
其他:一般設置唯一標識,比如主鍵
value類型:key對應value類型值,提高可讀性。
4.3、時效性
redis key一定要設置過期時間。要跟自己的業務場景,需要對key設置合理的過期時間。可以在寫入key時,就要追加過期時間;也可以在按照需要動態設置。
這里要注意:
- 不設置過期時間,這種key為永久key,會一直占用內存不釋放,時間久了,數量一多,就容易達到服務器的內存上限,導致宕機,開發時一般配合Key過期策略使用哦。
- key的時效性設置,必須根據業務場景進行評估,設置合理有效期;
4.4、靈活性
這個難介紹,一般key保證唯一時,可以使用主鍵,有的使用一個主鍵不能表達出全部意思,可以使用聯合主鍵。
比如:id為1的朋友圈下id為A的評論。
key | value |
---|---|
post:1:reply:A | 評論內容 |
post:1:reply:B | 評論內容 |
5、設置密碼
下面我們將介紹兩種常用的方法來為Redis設置密碼:
5.1、通過配置文件設置密碼
在Redis的配置文件redis.conf
中,可以通過以下步驟來設置密碼:
- 打開
redis.conf
文件(我的是在./www/server/redis/redis-7.2.3
目錄下) - 找到并取消注釋
requirepass
項
-
在
requirepass
后面添加你想要設置的密碼,如requirepass 1234
。 -
保存并關閉配置文件。
-
重新啟動Redis服務器,使密碼生效。
5.2、通過命令行設置密碼
除了通過配置文件,還可以直接通過命令行來為Redis設置密碼。打開終端并輸入以下命令:
redis-cli
接著,在命令行中輸入以下命令來設置密碼:
config set requirepass mypassword
運行上述命令后,Redis將返回OK
表示密碼設置成功。
驗證:
- 在redis命令行中,使用
auth mypassword
來驗證密碼 - 如果密碼正確,Redis將返回
OK
,表示密碼驗證成功。
5.3、更改密碼
- 在redis命令行中更改
config set requirepass newpassword
替換newpassword
為你想要設置的新密碼。
5.4、取消密碼
- 在redis命令行中更改
config set requirepass ""
運行上述命令后,Redis將返回OK
,表示密碼已成功取消。
多,就容易達到服務器的內存上限,導致宕機,開發時一般配合Key過期策略使用哦。
- key的時效性設置,必須根據業務場景進行評估,設置合理有效期;
4.4、靈活性
這個難介紹,一般key保證唯一時,可以使用主鍵,有的使用一個主鍵不能表達出全部意思,可以使用聯合主鍵。
比如:id為1的朋友圈下id為A的評論。
key | value |
---|---|
post:1:reply:A | 評論內容 |
post:1:reply:B | 評論內容 |