Redis之父:Salvatore Sanfilippo
本文基于Redis3.2.100版本(較早版本)
問題
Redis 有哪些數據類型,可參考《Redis常見的5種不同的數據類型詳解》
Redis 內部結構
Redis 使用場景
Redis 持久化機制
Redis 集群方案與實現
Redis 為什么是單線程的?
緩存雪崩、緩存穿透、緩存預熱、緩存更新、緩存降級
使用緩存的合理性問題
Redis常見的回收策略
Redis 簡介
REmote DIctionary Server(Redis) 是一個由Salvatore Sanfilippo寫的key-value存儲系統。
Redis是一個開源的使用ANSI C語言編寫、遵守BSD協議、支持網絡、可基于內存亦可持久化的日志型、Key-Value數據庫,并提供多種語言的API。
它通常被稱為數據結構服務器,因為值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等類型。
Redis 與其他 key - value 緩存產品有以下三個特點:
- Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用。
- Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等其他數據結構的存儲。
- Redis支持數據的備份,即master-slave模式的數據備份。
Redis 優勢
- 性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
- 豐富的數據類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數據類型操作。
- 操作原子性 – Redis的所有操作都是原子性的,意思就是要么成功執行要么失敗完全不執行。單個操作是原子性的。多個操作也支持事務,即原子性,通過MULTI和EXEC指令包起來。
- 豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。
Redis與其他key-value存儲有什么不同?
- Redis有著更為復雜的數據結構并且提供對他們的原子性操作,這是一個不同于其他數據庫的進化路徑。Redis的數據類型都是基于基本數據結構的同時對程序員透明,無需進行額外的抽象。
- Redis運行在內存中但是可以持久化到磁盤,所以在對不同數據集進行高速讀寫時需要權衡內存,因為數據量不能大于硬件內存。在內存數據庫方面的另一個優點是,相比在磁盤上相同的復雜的數據結構,在內存中操作起來非常簡單,這樣Redis可以做很多內部復雜性很強的事情。同時,在磁盤格式方面他們是緊湊的以追加的方式產生的,因為他們并不需要進行隨機訪問。
Redis 安裝
windows安裝
#解壓完成后,cmd打開命令窗口。可以把 redis 的路徑加到系統的環境變量里,這樣就省得再輸路徑了,后面的那個 #redis.windows.conf 可以省略,如果省略,會啟用默認的。
#開啟redis服務器
redis-server.exe redis.windows.conf
#redis客戶端連接
redis-cli.exe -h 127.0.0.1 -p 6379
Linux 下安裝
//參考其他
Redis 配置
Redis 的配置文件位于 Redis 安裝目錄下,文件名為 redis.conf(Windows 名為 redis.windows.conf)。
你可以通過 CONFIG 命令查看或設置配置項。命令大小寫不敏感。
127.0.0.1:6379> config get loglevel
1) "loglevel"
2) "warning"
#使用 * 號獲取所有配置項
CONFIG GET *
Redis 配置可以通過修改 redis.conf 文件或使用 CONFIG set 命令來修改配置。
127.0.0.1:6379> config set loglevel notice
OK
127.0.0.1:6379> config get loglevel
1) "loglevel"
2) "notice"
redis.conf 配置項說明如下:
序號 | 配置項 | 說明 |
---|---|---|
1 | daemonize no |
Redis 默認不是以守護進程的方式運行,可以通過該配置項修改,使用 yes 啟用守護進程(Windows 不支持守護線程的配置為 no ) |
2 | pidfile /var/run/redis.pid |
當 Redis 以守護進程方式運行時,Redis 默認會把 pid 寫入 /var/run/redis.pid 文件,可以通過 pidfile 指定 |
3 | port 6379 |
指定 Redis 監聽端口,默認端口為 6379,作者在自己的一篇博文中解釋了為什么選用 6379 作為默認端口,因為 6379 在手機按鍵上 MERZ 對應的號碼,而 MERZ 取自意大利歌女 Alessia Merz 的名字 |
4 | bind 127.0.0.1 |
綁定的主機地址 |
5 | timeout 300 |
當客戶端閑置多長秒后關閉連接,如果指定為 0 ,表示關閉該功能 |
6 | loglevel notice |
指定日志記錄級別,Redis 總共支持四個級別:debug、verbose、notice、warning,默認為 notice |
7 | logfile stdout |
日志記錄方式,默認為標準輸出,如果配置 Redis 為守護進程方式運行,而這里又配置為日志記錄方式為標準輸出,則日志將會發送給 /dev/null |
8 | databases 16 |
設置數據庫的數量,默認數據庫為0,可以使用SELECT 命令在連接上指定數據庫id |
9 |
save <seconds> <changes> Redis 默認配置文件中提供了三個條件:save 900 1****save 300 10****save 60 10000分別表示 900 秒(15 分鐘)內有 1 個更改,300 秒(5 分鐘)內有 10 個更改以及 60 秒內有 10000 個更改。 |
指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合 |
10 | rdbcompression yes |
指定存儲至本地數據庫時是否壓縮數據,默認為 yes,Redis 采用 LZF 壓縮,如果為了節省 CPU 時間,可以關閉該選項,但會導致數據庫文件變的巨大 |
11 | dbfilename dump.rdb |
指定本地數據庫文件名,默認值為 dump.rdb |
12 | dir ./ |
指定本地數據庫存放目錄 |
13 | slaveof <masterip> <masterport> |
設置當本機為 slav 服務時,設置 master 服務的 IP 地址及端口,在 Redis 啟動時,它會自動從 master 進行數據同步 |
14 | masterauth <master-password> |
當 master 服務設置了密碼保護時,slav 服務連接 master 的密碼 |
15 | requirepass foobared |
設置 Redis 連接密碼,如果配置了連接密碼,客戶端在連接 Redis 時需要通過 AUTH <password> 命令提供密碼,默認關閉 |
16 | maxclients 128 |
設置同一時間最大客戶端連接數,默認無限制,Redis 可以同時打開的客戶端連接數為 Redis 進程可以打開的最大文件描述符數,如果設置 maxclients 0,表示不作限制。當客戶端連接數到達限制時,Redis 會關閉新的連接并向客戶端返回 max number of clients reached 錯誤信息 |
17 | maxmemory <bytes> |
指定 Redis 最大內存限制,Redis 在啟動時會把數據加載到內存中,達到最大內存后,Redis 會先嘗試清除已到期或即將到期的 Key,當此方法處理 后,仍然到達最大內存設置,將無法再進行寫入操作,但仍然可以進行讀取操作。Redis 新的 vm 機制,會把 Key 存放內存,Value 會存放在 swap 區 |
18 | appendonly no |
指定是否在每次更新操作后進行日志記錄,Redis 在默認情況下是異步的把數據寫入磁盤,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為 redis 本身同步數據文件是按上面 save 條件來同步的,所以有的數據會在一段時間內只存在于內存中。默認為 no |
19 | appendfilename appendonly.aof |
指定更新日志文件名,默認為 appendonly.aof |
20 | appendfsync everysec |
指定更新日志條件,共有 3 個可選值:no:表示等操作系統進行數據緩存同步到磁盤(快)always:表示每次更新操作后手動調用 fsync() 將數據寫到磁盤(慢,安全)everysec:表示每秒同步一次(折中,默認值) |
21 | vm-enabled no |
指定是否啟用虛擬內存機制,默認值為 no,簡單的介紹一下,VM 機制將數據分頁存放,由 Redis 將訪問量較少的頁即冷數據 swap 到磁盤上,訪問多的頁面由磁盤自動換出到內存中(在后面的文章我會仔細分析 Redis 的 VM 機制) |
22 | vm-swap-file /tmp/redis.swap |
虛擬內存文件路徑,默認值為 /tmp/redis.swap,不可多個 Redis 實例共享 |
23 | vm-max-memory 0 |
將所有大于 vm-max-memory 的數據存入虛擬內存,無論 vm-max-memory 設置多小,所有索引數據都是內存存儲的(Redis 的索引數據 就是 keys),也就是說,當 vm-max-memory 設置為 0 的時候,其實是所有 value 都存在于磁盤。默認值為 0 |
24 | vm-page-size 32 |
Redis swap 文件分成了很多的 page,一個對象可以保存在多個 page 上面,但一個 page 上不能被多個對象共享,vm-page-size 是要根據存儲的 數據大小來設定的,作者建議如果存儲很多小對象,page 大小最好設置為 32 或者 64bytes;如果存儲很大大對象,則可以使用更大的 page,如果不確定,就使用默認值 |
25 | vm-pages 134217728 |
設置 swap 文件中的 page 數量,由于頁表(一種表示頁面空閑或使用的 bitmap)是在放在內存中的,,在磁盤上每 8 個 pages 將消耗 1byte 的內存。 |
26 | vm-max-threads 4 |
設置訪問swap文件的線程數,最好不要超過機器的核數,如果設置為0,那么所有對swap文件的操作都是串行的,可能會造成比較長時間的延遲。默認值為4 |
27 | glueoutputbuf yes |
設置在向客戶端應答時,是否把較小的包合并為一個包發送,默認為開啟 |
28 | hash-max-zipmap-entries 64 hash-max-zipmap-value 512 |
指定在超過一定的數量或者最大的元素超過某一臨界值時,采用一種特殊的哈希算法 |
29 | activerehashing yes |
指定是否激活重置哈希,默認為開啟(后面在介紹 Redis 的哈希算法時具體介紹) |
30 | include /path/to/local.conf |
指定包含其它的配置文件,可以在同一主機上多個Redis實例之間使用同一份配置文件,而同時各個實例又擁有自己的特定配置文件 |
Redis 數據類型
Redis支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
String(字符串)
string 是 redis 最基本的類型,你可以理解成與 Memcached 一模一樣的類型,一個 key 對應一個 value。
string 類型是二進制安全的。意思是 redis 的 string 可以包含任何數據。比如jpg圖片或者序列化的對象。
string 類型是 Redis 最基本的數據類型,string 類型的值最大能存儲 512MB。
Hash(哈希)
Redis hash 是一個鍵值(key=>value)對集合。
Redis hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用于存儲對象。
使用了 Redis HMSET, HGET 命令,HMSET 設置了兩個 field=>value 對, HGET 獲取對應 field 對應的 value。
每個 hash 可以存儲 2^32-1 鍵值對(40多億)。
List(列表)
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。
每個列表最多可存儲 2^32 - 1 元素 。
Set(集合)
Redis 的 Set 是 string 類型的無序集合。相當于HashSet。
集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是 O(1)。
Set集合內元素具有唯一性,第二次插入的元素將被忽略 。
每個集合中最大的成員數為 2^32 - 1 .
zset(sorted set:有序集合)
Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
zset的成員是唯一的,但分數(score)卻可以重復。
擴展:
各個數據類型應用場景:
類型 | 簡介 | 特性 | 場景 |
---|---|---|---|
String(字符串) | 二進制安全 | 可以包含任何數據,比如jpg圖片或者序列化的對象,一個鍵最大能存儲512M | --- |
Hash(字典) | 鍵值對集合,即編程語言中的Map類型 | 適合存儲對象,并且可以像數據庫中update一個屬性一樣只修改某一項屬性值(Memcached中需要取出整個字符串反序列化成對象修改完再序列化存回去) | 存儲、讀取、修改用戶屬性 |
List(列表) | 鏈表(雙向鏈表) | 增刪快,提供了操作某一段元素的API | 1,最新消息排行等功能(比如朋友圈的時間線) 2,消息隊列 |
Set(集合) | 哈希表實現,元素不重復 | 1、添加、刪除,查找的復雜度都是O(1) 2、為集合提供了求交集、并集、差集等操作 | 1、共同好友 2、利用唯一性,統計訪問網站的所有獨立ip 3、好友推薦時,根據tag求交集,大于某個閾值就可以推薦 |
Sorted Set(有序集合) | 將Set中的元素增加一個權重參數score,元素按score有序排列 | 數據插入集合時,已經進行天然排序 | 1、排行榜 2、帶權重的消息隊列 |
注意:Redis支持多個數據庫,并且每個數據庫的數據是隔離的不能共享,并且基于單機才有,如果是集群就沒有數據庫的概念。
Redis是一個字典結構的存儲服務器,而實際上一個Redis實例提供了多個用來存儲數據的字典,客戶端可以指定將數據存儲在哪個字典中。這與我們熟知的在一個關系數據庫實例中可以創建多個數據庫類似,所以可以將其中的每個字典都理解成一個獨立的數據庫。
每個數據庫對外都是一個從0開始的遞增數字命名,Redis默認支持16個數據庫(可以通過配置文件支持更多,無上限),可以通過配置databases來修改這一數字。客戶端與Redis建立連接后會自動選擇0號數據庫,不過可以隨時使用SELECT命令更換數據庫,如要選擇1號數據庫:
redis> SELECT 1
OK
redis [1] > GET foo
(nil)
然而這些以數字命名的數據庫又與我們理解的數據庫有所區別。首先Redis不支持自定義數據庫的名字,每個數據庫都以編號命名,開發者必須自己記錄哪些數據庫存儲了哪些數據。另外Redis也不支持為每個數據庫設置不同的訪問密碼,所以一個客戶端要么可以訪問全部數據庫,要么連一個數據庫也沒有權限訪問。最重要的一點是多個數據庫之間并不是完全隔離的,比如FLUSHALL命令可以清空一個Redis實例中所有數據庫中的數據。綜上所述,這些數據庫更像是一種命名空間,而不適宜存儲不同應用程序的數據。比如可以使用0號數據庫存儲某個應用生產環境中的數據,使用1號數據庫存儲測試環境中的數據,但不適宜使用0號數據庫存儲A應用的數據而使用1號數據庫B應用的數據,不同的應用應該使用不同的Redis實例存儲數據。由于Redis非常輕量級,一個空Redis實例占用的內在只有1M左右,所以不用擔心多個Redis實例會額外占用很多內存。
示例:
#開啟客戶端連接
F:\redis>redis-cli.exe -h 127.0.0.1 -p 6379
#開啟默認連接本地的客戶端
redis-cli.exe
#字符串操作
127.0.0.1:6379> set hero "batman dark knight"
OK
127.0.0.1:6379> get hero
"batman dark knight"
#Hash(哈希)操作 可以用hmset/hmget, 或者hset/hget
127.0.0.1:6379> hmset car tire "good year"
OK
127.0.0.1:6379> hmset car corlor "black"
OK
127.0.0.1:6379> hmget car corlor
1) "black"
127.0.0.1:6379> hget car tire
"good year"
#List(列表)lpush 在左邊插入 ,rpush 在最右邊插入,lrange 遍歷List
127.0.0.1:6379> lpush fruit apple
(integer) 1
127.0.0.1:6379> lpush fruit orange banana
(integer) 3
127.0.0.1:6379> lpush fruit watermelon berry
(integer) 5
127.0.0.1:6379> lrange fruit 0 10
1) "berry"
2) "watermelon"
3) "banana"
4) "orange"
5) "apple"
#Set(集合)操作,sadd 添加 smembers 遍歷set
127.0.0.1:6379> sadd animal tiger rabbit cow monkey
(integer) 4
127.0.0.1:6379> sadd animal cat dog
(integer) 2
127.0.0.1:6379> sadd animal sheep
(integer) 1
127.0.0.1:6379> smembers animal
1) "tiger"
2) "monkey"
3) "rabbit"
4) "cow"
5) "dog"
6) "cat"
7) "sheep"
#zset(sorted set:有序集合)操作,zadd 添加 zrangebyscore 或zrange 遍歷zset
#zadd hourse 0 wall 在使用zadd 添加元素時會給一個分值,作為排序大小,當zrange時會從小到大排列遍歷,當
#分數值相同時從值的首字母按a-z排序
127.0.0.1:6379> zadd body 0 nose
(integer) 1
127.0.0.1:6379> zadd body 0 head
(integer) 1
127.0.0.1:6379> zadd body 0 face
(integer) 1
127.0.0.1:6379> zrangebyscore body 0 10
1) "face"
2) "head"
3) "nose"
127.0.0.1:6379> zadd hourse 0 wall
(integer) 1
127.0.0.1:6379> zadd hourse 10 windows
(integer) 1
127.0.0.1:6379> zadd hourse 11 table
(integer) 1
127.0.0.1:6379> zadd hourse 12 frudge
(integer) 1
127.0.0.1:6379> zadd hourse 13 box
(integer) 1
127.0.0.1:6379> zrangebyscore hourse 0 100
1) "wall"
2) "windows"
3) "table"
4) "frudge"
5) "box"
127.0.0.1:6379> zrange hourse 0 100
1) "wall"
2) "windows"
3) "table"
4) "frudge"
5) "box"
127.0.0.1:6379> zrange body 0 100
1) "face"
2) "head"
3) "nose"
127.0.0.1:6379>
#刪除
del key
Redis 命令
#連接到主機為 127.0.0.1,端口為 6379 ,密碼為 mypass 的 redis 服務上。
redis-cli -h 127.0.0.1 -p 6379 -a "mypass"
#有時候會有中文亂碼。
#要在 redis-cli 后面加上 --raw
redis-cli --raw
Redis 鍵(key)
Redis 鍵相關的基本命令:
序號 | 命令及描述 |
---|---|
1 | DEL key 該命令用于在 key 存在時刪除 key。 |
2 | DUMP key 序列化給定 key ,并返回被序列化的值。 |
3 | EXISTS key 檢查給定 key 是否存在。 |
4 | EXPIRE key seconds 為給定 key 設置過期時間,以秒計。 |
5 | EXPIREAT key timestamp EXPIREAT 的作用和 EXPIRE 類似,都用于為 key 設置過期時間。 不同在于 EXPIREAT 命令接受的時間參數是 UNIX 時間戳(unix timestamp)。 |
6 | PEXPIRE key milliseconds 設置 key 的過期時間以毫秒計。 |
7 | PEXPIREAT key milliseconds-timestamp 設置 key 過期時間的時間戳(unix timestamp) 以毫秒計 |
8 | KEYS pattern 查找所有符合給定模式( pattern)的 key 。 |
9 | MOVE key db 將當前數據庫的 key 移動到給定的數據庫 db 當中。 |
10 | PERSIST key 移除 key 的過期時間,key 將持久保持。 |
11 | PTTL key 以毫秒為單位返回 key 的剩余的過期時間。 |
12 | TTL key 以秒為單位,返回給定 key 的剩余生存時間(TTL, time to live)。 |
13 | RANDOMKEY 從當前數據庫中隨機返回一個 key 。 |
14 | RENAME key newkey 修改 key 的名稱 |
15 | RENAMENX key newkey 僅當 newkey 不存在時,將 key 改名為 newkey 。 |
16 | [SCAN cursor MATCH pattern] [COUNT count] 迭代數據庫中的數據庫鍵。 |
17 | TYPE key 返回 key 所儲存的值的類型。 |
Redis 字符串(String)
常用的 redis 字符串命令:
序號 | 命令及描述 |
---|---|
1 | SET key value 設置指定 key 的值 |
2 | GET key 獲取指定 key 的值。 |
3 | GETRANGE key start end 返回 key 中字符串值的子字符 |
4 | GETSET key value 將給定 key 的值設為 value ,并返回 key 的舊值(old value)。 |
5 | GETBIT key offset 對 key 所儲存的字符串值,獲取指定偏移量上的位(bit)。 |
6 | [MGET key1 key2..] 獲取所有(一個或多個)給定 key 的值。 |
7 | SETBIT key offset value 對 key 所儲存的字符串值,設置或清除指定偏移量上的位(bit)。 |
8 | SETEX key seconds value 將值 value 關聯到 key ,并將 key 的過期時間設為 seconds (以秒為單位)。 |
9 | SETNX key value 只有在 key 不存在時設置 key 的值。 |
10 | SETRANGE key offset value 用 value 參數覆寫給定 key 所儲存的字符串值,從偏移量 offset 開始。 |
11 | STRLEN key 返回 key 所儲存的字符串值的長度。 |
12 | [MSET key value key value ...] 同時設置一個或多個 key-value 對。 |
13 | [MSETNX key value key value ...] 同時設置一個或多個 key-value 對,當且僅當所有給定 key 都不存在。 |
14 | PSETEX key milliseconds value 這個命令和 SETEX 命令相似,但它以毫秒為單位設置 key 的生存時間,而不是像 SETEX 命令那樣,以秒為單位。 |
15 | INCR key 將 key 中儲存的數字值增一。 |
16 | INCRBY key increment 將 key 所儲存的值加上給定的增量值(increment) 。 |
17 | INCRBYFLOAT key increment 將 key 所儲存的值加上給定的浮點增量值(increment) 。 |
18 | DECR key 將 key 中儲存的數字值減一。 |
19 | DECRBY key decrement key 所儲存的值減去給定的減量值(decrement) 。 |
20 | APPEND key value 如果 key 已經存在并且是一個字符串, APPEND 命令將指定的 value 追加到該 key 原來值(value)的末尾。 |
Redis 哈希(Hash)
Redis hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用于存儲對象。
注意:哈希表的field 和 value都是String類型的,當我們要往里塞其他哈希表或者List集合等時,必須用FastJson等工具轉化為字符串類型。
redis hash 基本的相關命令:
序號 | 命令及描述 |
---|---|
1 | [HDEL key field1 field2] 刪除一個或多個哈希表字段 |
2 | HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。 |
3 | HGET key field 獲取存儲在哈希表中指定字段的值。 |
4 | HGETALL key 獲取在哈希表中指定 key 的所有字段和值 |
5 | HINCRBY key field increment 為哈希表 key 中的指定字段的整數值加上增量 increment,increment可以是正負數 。 |
6 | HINCRBYFLOAT key field increment 為哈希表 key 中的指定字段的浮點數值加上增量 increment,increment可以是正負數。 |
7 | HKEYS key 獲取所有哈希表中的字段 |
8 | HLEN key 獲取哈希表中字段的數量 |
9 | [HMGET key field1 field2] 獲取所有給定字段的值 |
10 | [HMSET key field1 value1 field2 value2 ] 同時將多個 field-value (域-值)對設置到哈希表 key 中。 |
11 | HSET key field value 將哈希表 key 中的字段 field 的值設為 value 。 |
12 | HSETNX key field value 只有在字段 field 不存在時,設置哈希表字段的值。 |
13 | HVALS key 獲取哈希表中所有值。 |
14 | [HSCAN key cursor MATCH pattern] [COUNT count] 迭代哈希表中的鍵值對。 |
Redis 列表(List)
Redis列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊) 。
列表相關的基本命令:
序號 | 命令及描述 |
---|---|
1 | [BLPOP key1 key2 ] timeout 移出并獲取列表的第一個元素, 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。 |
2 | [BRPOP key1 key2 ] timeout 移出并獲取列表的最后一個元素, 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。 |
3 | BRPOPLPUSH source destination timeout 從列表中彈出一個值,將彈出的元素插入到另外一個列表中并返回它; 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。 |
4 | LINDEX key index 通過索引獲取列表中的元素 |
5 | LINSERT key BEFORE|AFTER pivot value 在列表的元素前或者后插入元素 |
6 | LLEN key 獲取列表長度 |
7 | LPOP key 移出并獲取列表的第一個元素 |
8 | [LPUSH key value1 value2] 將一個或多個值插入到列表頭部 |
9 | LPUSHX key value 將一個值插入到已存在的列表頭部 |
10 | LRANGE key start stop 獲取列表指定范圍內的元素 |
11 | LREM key count value 移除列表元素 |
12 | LSET key index value 通過索引設置列表元素的值 |
13 | LTRIM key start stop 對一個列表進行修剪(trim),就是說,讓列表只保留指定區間內的元素,不在指定區間之內的元素都將被刪除。 |
14 | RPOP key 移除列表的最后一個元素,返回值為移除的元素。 |
15 | RPOPLPUSH source destination 移除列表的最后一個元素,并將該元素添加到另一個列表并返回 |
16 | [RPUSH key value1 value2] 在列表中添加一個或多個值 |
17 | RPUSHX key value 為已存在的列表添加值 |
Redis 集合(Set)
Redis 的 Set 是 String 類型的無序集合。集合成員是唯一的,這就意味著集合中不能出現重復的數據。
Redis 中集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是 O(1)。
Redis 集合基本命令:
序號 | 命令及描述 |
---|---|
1 | [SADD key member1 member2] 向集合添加一個或多個成員 |
2 | SCARD key 獲取集合的成員數 |
3 | [SDIFF key1 key2] 返回給定集合key1與其他集合的差集 |
4 | [SDIFFSTORE destination key1 key2] 返回給定集合key1與其他集合的差集并存儲在 destination 中 |
5 | [SINTER key1 key2] 返回給定所有集合的交集 |
6 | [SINTERSTORE destination key1 key2] 返回給定所有集合的交集并存儲在 destination 中 |
7 | SISMEMBER key member 判斷 member 元素是否是集合 key 的成員 |
8 | SMEMBERS key 返回集合中的所有成員 |
9 | SMOVE source destination member 將 member 元素從 source 集合移動到 destination 集合,如果destination 集合已經包含了這個元素,也會從source 集合移出,只是destination 集合已經有值了所以沒變。 |
10 | SPOP key 移除并返回集合中的一個隨機元素 |
11 | [SRANDMEMBER key count] 返回集合中一個或多個隨機元素 |
12 | [SREM key member1 member2] 移除集合中一個或多個成員 |
13 | [SUNION key1 key2] 返回所有給定集合的并集 |
14 | [SUNIONSTORE destination key1 key2] 所有給定集合的并集存儲在 destination 集合中 |
15 | [SSCAN key cursor MATCH pattern] [COUNT count] 迭代集合中的元素 |
Redis 有序集合(sorted set)
Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重復。
集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。
原文中說,集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)其實不太準確。
其實在redis sorted sets里面當items內容大于64的時候同時使用了hash和skiplist兩種設計實現。這也會為了排序和查找性能做的優化。所以如上可知:
添加和刪除都需要修改skiplist,所以復雜度為O(log(n))。
但是如果僅僅是查找元素的話可以直接使用hash,其復雜度為O(1)
其他的range操作復雜度一般為O(log(n))
當然如果是小于64的時候,因為是采用了ziplist的設計,其時間復雜度為O(n)
redis 有序集合的基本命令:
序號 | 命令及描述 |
---|---|
1 | [ZADD key score1 member1 score2 member2] 向有序集合添加一個或多個成員,或者更新已存在成員的分數 |
2 | ZCARD key 獲取有序集合的成員數 |
3 | ZCOUNT key min max 計算在有序集合中指定區間分數的成員數 |
4 | ZINCRBY key increment member 有序集合中對指定成員的分數加上增量 increment |
5 | [ZINTERSTORE destination numkeys key key ...] 計算給定的一個或多個有序集的交集并將結果集存儲在新的有序集合 key 中,numkeys表示有幾個集合取交集 |
6 | ZLEXCOUNT key min max 在有序集合中計算指定字典區間內成員數量 |
7 | [ZRANGE key start stop WITHSCORES] 通過索引區間返回有序集合指定區間內的成員 |
8 | [ZRANGEBYLEX key min max LIMIT offset count] 通過字典區間返回有序集合的成員 |
9 | [ZRANGEBYSCORE key min max WITHSCORES] [LIMIT] 通過分數返回有序集合指定區間內的成員 |
10 | ZRANK key member 返回有序集合中指定成員的索引 |
11 | [ZREM key member member ...] 移除有序集合中的一個或多個成員 |
12 | ZREMRANGEBYLEX key min max 移除有序集合中給定的字典區間的所有成員 |
13 | ZREMRANGEBYRANK key start stop 移除有序集合中給定的排名區間的所有成員 |
14 | ZREMRANGEBYSCORE key min max 移除有序集合中給定的分數區間的所有成員 |
15 | [ZREVRANGE key start stop WITHSCORES] 返回有序集中指定區間內的成員,通過索引,分數從高到低 |
16 | [ZREVRANGEBYSCORE key max min WITHSCORES] 返回有序集中指定分數區間內的成員,分數從高到低排序 |
17 | ZREVRANK key member 返回有序集合中指定成員的排名,有序集成員按分數值遞減(從大到小)排序 |
18 | ZSCORE key member 返回有序集中,成員的分數值 |
19 | [ZUNIONSTORE destination numkeys key key ...] 計算給定的一個或多個有序集的并集,并存儲在新的 key 中 |
20 | [ZSCAN key cursor MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成員和元素分值) |
Redis HyperLogLog
什么是基數?
比如數據集 {1, 3, 5, 7, 5, 7, 8}, 那么這個數據集的基數集為 {1, 3, 5 ,7, 8}, 基數(不重復元素)為5。 基數估計就是在誤差可接受的范圍內,快速計算基數。
Redis 在 2.8.9 版本添加了 HyperLogLog 結構。
Redis HyperLogLog 是用來做基數統計的算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定 的、并且是很小的。
在 Redis 里面,每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基 數。這和計算基數時,元素越多耗費內存就越多的集合形成鮮明對比。
但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
redis HyperLogLog 的基本命令:
序號 | 命令及描述 |
---|---|
1 | [PFADD key element element ...] 添加指定元素到 HyperLogLog 中。 |
2 | [PFCOUNT key key ...] 返回給定 HyperLogLog 的基數估算值。 |
3 | [PFMERGE destkey sourcekey sourcekey ...] 將多個 HyperLogLog 合并為一個 HyperLogLog |
Redis 發布訂閱
Redis 發布訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。
Redis 客戶端可以訂閱任意數量的頻道。
redis 發布訂閱常用命令:
序號 | 命令及描述 |
---|---|
1 | [PSUBSCRIBE pattern pattern ...] 訂閱一個或多個符合給定模式的頻道。 |
2 | [PUBSUB subcommand argument [argument ...]] 查看訂閱與發布系統狀態。 |
3 | PUBLISH channel message 將信息發送到指定的頻道。 |
4 | [PUNSUBSCRIBE pattern [pattern ...]] 退訂所有給定模式的頻道。 |
5 | [SUBSCRIBE channel channel ...] 訂閱給定的一個或多個頻道的信息。 |
6 | [UNSUBSCRIBE channel [channel ...]] 指退訂給定的頻道。 |
實例:
Redis 事務
Redis 事務可以一次執行多個命令, 并且帶有以下三個重要的保證:
- 批量操作在發送 EXEC 命令前被放入隊列緩存。
- 收到 EXEC 命令后進入事務執行,事務中任意命令執行失敗,其余的命令依然被執行。
- 在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中。
一個事務從開始到執行會經歷以下三個階段:
- 開始事務。
- 命令入隊。
- 執行事務。
注意:單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,所以 Redis 事務的執行并不是原子性的。
事務可以理解為一個打包的批量執行腳本,但批量指令并非原子化的操作,中間某條指令的失敗不會導致前面已做指令的回滾,也不會造成后續的指令不做。
redis 事務的相關命令:
序號 | 命令及描述 |
---|---|
1 | DISCARD 取消事務,放棄執行事務塊內的所有命令。 |
2 | EXEC 執行所有事務塊內的命令。 |
3 | MULTI 標記一個事務塊的開始。 |
4 | UNWATCH 取消 WATCH 命令對所有 key 的監視。 |
5 | [WATCH key key ...] 監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷。 |
示例:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set godfather mike
QUEUED
127.0.0.1:6379> set blacked xuwenbiao
QUEUED
127.0.0.1:6379> sadd family me father mother sister wife "bro in law"
QUEUED
127.0.0.1:6379> get godfather
QUEUED
127.0.0.1:6379> get blacked
QUEUED
127.0.0.1:6379> smembers family
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) (integer) 6
4) "mike"
5) "xuwenbiao"
6) 1) "me"
2) "mother"
3) "bro in law"
4) "wife"
5) "father"
6) "sister"
Redis 腳本
Redis 腳本使用 Lua 解釋器來執行腳本。 Redis 2.6 版本通過內嵌支持 Lua 環境。執行腳本的常用命令為 EVAL。
Q:Redis 腳本的作用,使用場景是什么?
Redis 連接
Redis 連接命令主要是用于連接 redis 服務。
Redis 連接命令
redis 連接的基本命令:
序號 | 命令及描述 |
---|---|
1 | AUTH password 驗證密碼是否正確 |
2 | ECHO message 打印字符串 |
3 | PING 查看服務是否運行 |
4 | QUIT 關閉當前連接 |
5 | SELECT index 切換到指定的數據庫 |
疑問:
Q:SELECT index 切換到指定的數據庫有什么用,redis的數據庫是干嘛用的?是持久化后的數據保存的地方么?指定不同的數據庫是為了什么?什么場景下這樣做?
Q:執行 AUTH "password" 報錯,報錯信息:ERR Client sent AUTH, but no password is set。
A:這是由于redis沒有設置密碼,可以選擇設置密碼,執行該命令便不會有這個報錯。
解決方案一:
在redis配置文件中redis.conf加入:
requirePass: 你的密碼
解決方案二:
把上面的配置中password一行去掉,既然沒密碼,就不要寫。
spring:
redis:
database: 0
host: 127.0.0.1
port: 6379
timeout: 10000
Redis 服務器
Redis 服務器命令主要是用于管理 redis 服務。
redis 服務器的相關命令:
序號 | 命令及描述 |
---|---|
1 | BGREWRITEAOF 異步執行一個 AOF(AppendOnly File) 文件重寫操作 |
2 | BGSAVE 在后臺異步保存當前數據庫的數據到磁盤 |
3 | [CLIENT KILL ip:port] [ID client-id] 關閉客戶端連接 |
4 | CLIENT LIST 獲取連接到服務器的客戶端連接列表 |
5 | CLIENT GETNAME 獲取連接的名稱 |
6 | CLIENT PAUSE timeout 在指定時間內終止運行來自客戶端的命令 |
7 | CLIENT SETNAME connection-name 設置當前連接的名稱 |
8 | CLUSTER SLOTS 獲取集群節點的映射數組 |
9 | COMMAND 獲取 Redis 命令詳情數組 |
10 | COMMAND COUNT 獲取 Redis 命令總數 |
11 | COMMAND GETKEYS 獲取給定命令的所有鍵 |
12 | TIME 返回當前服務器時間 |
13 | [COMMAND INFO command-name command-name ...] 獲取指定 Redis 命令描述的數組 |
14 | CONFIG GET parameter 獲取指定配置參數的值 |
15 | CONFIG REWRITE 對啟動 Redis 服務器時所指定的 redis.conf 配置文件進行改寫 |
16 | CONFIG SET parameter value 修改 redis 配置參數,無需重啟 |
17 | CONFIG RESETSTAT 重置 INFO 命令中的某些統計數據 |
18 | DBSIZE 返回當前數據庫的 key 的數量 |
19 | DEBUG OBJECT key 獲取 key 的調試信息 |
20 | DEBUG SEGFAULT 讓 Redis 服務崩潰 |
21 | FLUSHALL 刪除所有數據庫的所有key |
22 | FLUSHDB 刪除當前數據庫的所有key |
23 | [INFO section] 獲取 Redis 服務器的各種信息和統計數值 |
24 | LASTSAVE 返回最近一次 Redis 成功將數據保存到磁盤上的時間,以 UNIX 時間戳格式表示 |
25 | MONITOR 實時打印出 Redis 服務器接收到的命令,調試用 |
26 | ROLE 返回主從實例所屬的角色 |
27 | SAVE 同步保存數據到硬盤 |
28 | [SHUTDOWN NOSAVE] [SAVE] 異步保存數據到硬盤,并關閉服務器 |
29 | SLAVEOF host port 將當前服務器轉變為指定服務器的從屬服務器(slave server) |
30 | [SLOWLOG subcommand argument] 管理 redis 的慢日志 |
31 | SYNC 用于復制功能(replication)的內部命令 |
Redis GEO
Redis GEO 主要用于存儲地理位置信息,并對存儲的信息進行操作,該功能在 Redis 3.2 版本新增。
Redis GEO 操作方法有:
- geoadd:添加地理位置的坐標。
- geopos:獲取地理位置的坐標。
- geodist:計算兩個位置之間的距離。
- georadius:根據用戶給定的經緯度坐標來獲取指定范圍內的地理位置集合。
- georadiusbymember:根據儲存在位置集合里面的某個地點獲取指定范圍內的地理位置集合。
- geohash:返回一個或多個位置對象的 geohash 值。
Q:Redis GEO 主要用于存儲地理位置信息,并對存儲的信息進行操作.是專門用于地理位置的命令,滴滴,谷歌地圖等用的?
Redis 高級教程
Redis 數據備份與恢復
備份
Redis SAVE 命令用于創建當前數據庫的備份。
該命令將在 redis 安裝目錄中創建dump.rdb文件。
Bgsave
創建 redis 備份文件也可以使用命令 BGSAVE,該命令在后臺執行。
恢復數據
如果需要恢復數據,只需將備份文件 (dump.rdb) 移動到 redis 安裝目錄并啟動服務即可。獲取 redis 目錄可以使用 CONFIG 命令。
CONFIG GET dir
1) "dir"
2) "/usr/local/redis/bin"
以上命令 CONFIG GET dir 輸出的 redis 安裝目錄為 /usr/local/redis/bin 。
Redis 安全
我們可以通過 redis 的配置文件設置密碼參數,這樣客戶端連接到 redis 服務就需要密碼驗證,這樣可以讓你的 redis 服務更安全。
//查看是否設置了密碼驗證
CONFIG get requirepass
//如果需要密碼則登錄后要進行密碼授權,才能進行redis操作,如get/set等
auth "密碼"
//默認情況下 requirepass 參數是空的,這就意味著你無需通過密碼驗證就可以連接到 redis 服務。
//修改密碼命令
CONFIG set requirepass "密碼"
//如果不想要設置密碼了,可以執行命令
CONFIG set requirepass ""
Redis 性能測試
Redis 性能測試是通過同時執行多個命令實現的。
redis 性能測試的基本命令如下:
redis-benchmark [option] [option value]
注意:該命令是在 redis 的目錄下執行的,而不是 redis 客戶端的內部指令。
redis 性能測試工具可選參數如下所示:
序號 | 選項 | 描述 | 默認值 |
---|---|---|---|
1 | -h | 指定服務器主機名 | 127.0.0.1 |
2 | -p | 指定服務器端口 | 6379 |
3 | -s | 指定服務器 socket | |
4 | -c | 指定并發連接數 | 50 |
5 | -n | 指定請求數 | 10000 |
6 | -d | 以字節的形式指定 SET/GET 值的數據大小 | 2 |
7 | -k | 1=keep alive 0=reconnect | 1 |
8 | -r | SET/GET/INCR 使用隨機 key, SADD 使用隨機值 | |
9 | -P | 通過管道傳輸 <numreq> 請求 | 1 |
10 | -q | 強制退出 redis。僅顯示 query/sec 值 | |
11 | --csv | 以 CSV 格式輸出 | |
12 | -l | 生成循環,永久執行測試 | |
13 | -t | 僅運行以逗號分隔的測試命令列表。 | |
14 | -I | Idle 模式。僅打開 N 個 idle 連接并等待。 |
//測試主機為 127.0.0.1,端口號為 6379,執行的命令為 set,lpush,請求數為 10000,通過 -q 參數讓結果只顯示每秒執行的請求數。
redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q
//測試本地主機
redis-benchmark.exe -n 10000 -q
//測試主機為 127.0.0.1,端口號為 6379,執行所有命令,請求數為 10000,并發數 100,通過 -q 參數讓結果只顯示每秒執行的請求數。
E:\redis>redis-benchmark.exe -h 127.0.0.1 -p 6379 -c 100 -n 10000 -q
PING_INLINE: 12300.12 requests per second
PING_BULK: 11918.95 requests per second
SET: 12239.90 requests per second
GET: 12722.65 requests per second
INCR: 12165.45 requests per second
LPUSH: 12515.64 requests per second
RPUSH: 12285.01 requests per second
LPOP: 12150.67 requests per second
RPOP: 12484.39 requests per second
SADD: 12422.36 requests per second
SPOP: 12254.90 requests per second
LPUSH (needed to benchmark LRANGE): 12330.46 requests per second
LRANGE_100 (first 100 elements): 11848.34 requests per second
LRANGE_300 (first 300 elements): 7961.78 requests per second
LRANGE_500 (first 450 elements): 6648.94 requests per second
LRANGE_600 (first 600 elements): 5646.53 requests per second
MSET (10 keys): 12722.65 requests per second
//測試主機為 127.0.0.1,端口號為 6379,執行的命令為 set,get,lpush,請求數為 10000,通過 -q 參數讓結果只顯示每秒執行的請求數。
E:\redis>redis-benchmark.exe -h 127.0.0.1 -p 6379 -t set,get,lpush -n 10000 -q
SET: 12919.90 requests per second
GET: 12804.10 requests per second
LPUSH: 12787.72 requests per second
Redis 客戶端連接
Redis 通過監聽一個 TCP 端口或者 Unix socket 的方式來接收來自客戶端的連接,當一個連接建立后,Redis 內部會進行以下一些操作:
- 首先,客戶端 socket 會被設置為非阻塞模式,因為 Redis 在網絡事件處理上采用的是非阻塞多路復用模型。
- 然后為這個 socket 設置 TCP_NODELAY 屬性,禁用 Nagle 算法
- 然后創建一個可讀的文件事件用于監聽這個客戶端 socket 的數據發送
最大連接數
在 Redis2.4 中,最大連接數是被直接硬編碼在代碼里面的,而在2.6版本中這個值變成可配置的。
maxclients 的默認值是 10000,你也可以在 redis.conf 中對這個值進行修改。
//最大連接數
config get maxclients
//設置最大連接數為1000
config set maxclients 1000
//以下實例我們在服務啟動時設置最大連接數為 1000:
redis-server --maxclients 1000
//windows下
E:\redis>redis-server.exe redis.windows.conf --maxclients 1000
客戶端命令
S.N. | 命令 | 描述 |
---|---|---|
1 | CLIENT LIST | 返回連接到 redis 服務的客戶端列表 |
2 | CLIENT SETNAME | 設置當前連接的名稱 |
3 | CLIENT GETNAME | 獲取通過 CLIENT SETNAME 命令設置的服務名稱 |
4 | CLIENT PAUSE | 掛起客戶端連接,指定掛起的時間以毫秒計 |
5 | CLIENT KILL | 關閉客戶端連接 |
//掛起客戶端連接50000毫秒,這時候客戶端不能接受任何指令了,而且關閉不了,重新進入也不行,只能等待客戶端掛起時間達到后,或者關閉服務端redis服務器,才行
client pause 50000
Redis 管道技術
Redis是一種基于客戶端-服務端模型以及請求/響應協議的TCP服務。這意味著通常情況下一個請求會遵循以下步驟:
- 客戶端向服務端發送一個查詢請求,并監聽Socket返回,通常是以阻塞模式,等待服務端響應。
- 服務端處理命令,并將結果返回給客戶端。
Redis 管道技術可以在服務端未響應時,客戶端可以繼續向服務端發送請求,并最終一次性讀取所有服務端的響應。
Q:Redis 管道技術是基于NIO么?
Redis 分區
分區是分割數據到多個Redis實例的處理過程,因此每個實例只保存所有key的一個子集。
分區的優勢
- 通過利用多臺計算機內存的和值,允許我們構造更大的數據庫。
- 通過多核和多臺計算機,允許我們擴展計算能力;通過多臺計算機和網絡適配器,允許我們擴展網絡帶寬。
分區的不足
redis的一些特性在分區方面表現的不是很好:
- 涉及多個key的操作通常是不被支持的。舉例來說,當兩個set映射到不同的redis實例上時,你就不能對這兩個set執行交集操作。
- 涉及多個key的redis事務不能使用。
- 當使用分區時,數據處理較為復雜,比如你需要處理多個rdb/aof文件,并且從多個實例和主機備份持久化文件。
- 增加或刪除容量也比較復雜。redis集群大多數支持在運行時增加、刪除節點的透明數據平衡的能力,但是類似于客戶端分區、代理等其他系統則不支持這項特性。然而,一種叫做presharding的技術對此是有幫助的。
分區類型
范圍分區
最簡單的分區方式是按范圍分區,就是映射一定范圍的對象到特定的Redis實例。
比如,ID從0到10000的用戶會保存到實例R0,ID從10001到 20000的用戶會保存到R1,以此類推。
這種方式是可行的,并且在實際中使用,不足就是要有一個區間范圍到實例的映射表。這個表要被管理,同時還需要各 種對象的映射表,通常對Redis來說并非是好的方法。
哈希分區
另外一種分區方法是hash分區。這對任何key都適用,也無需是object_name:這種形式,像下面描述的一樣簡單:
- 用一個hash函數將key轉換為一個數字,比如使用crc32 hash函數。對key foobar執行crc32(foobar)會輸出類似93024922的整數。
- 對這個整數取模,將其轉化為0-3之間的數字,就可以將這個整數映射到4個Redis實例中的一個了。93024922 % 4 = 2,就是說key foobar應該被存到R2實例中。注意:取模操作是取除的余數,通常在多種編程語言中用%操作符實現。
疑問:
1、Q:redis HSCAN 命令的使用場景?如何使用?
Java 使用 Redis
需要依賴Java redis 驅動 :jedis
Redis與SpringBoot整合有兩種方式,第一種是使用Jedis,它是Redis官方推薦的面向Java的操作Redis的客戶端,第二種是使用RedisTemplate,它是SpringDataRedis中對JedisApi的高度封裝。我此次使用的是RedisTemplate,并整理了redis工具類方便大家使用
示例:
spring整合jedis
jedis依賴:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<optional>true</optional>
</dependency>
public class RedisTest {
public static void main(String[] args) {
//不傳參數默認是localhost
//Jedis jedis = new Jedis();
//本地localhost兩種傳值方式
//Jedis jedis = new Jedis("localhost");
Jedis jedis = new Jedis("127.0.0.1");
System.out.println("連接成功");
System.out.println(jedis.ping());
jedis.set("hero", "I AM BATMAN");
String hero = jedis.get("hero");
System.out.println("hero 返回" + hero);
jedis.lpush("Europe", "German");
jedis.lpush("Europe", "France");
jedis.lpush("Europe", "Duke");
List<String> europe = jedis.lrange("Europe", 0, 2);
for (String s : europe) {
System.out.println("Europe list:" + s);
}
Set<String> keys = jedis.keys("*");
for (String key : keys) {
System.out.println("redis key:"+key);
//不同類型的數據類型要用不同的獲取方式,否則報錯Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException:
// WRONGTYPE Operation against a key holding the wrong kind of value
//System.out.println("redis data :"+jedis.get(key));
}
}
}
輸出:
連接成功
PONG
hero 返回I AM BATMAN
Europe list:Duke
Europe list:France
Europe list:German
redis key:music
redis key:phone
redis key:hero
redis key:Europe
redis key:mylist
springboot整合redis
依賴:
<!-- 配置使用 redis 啟動器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.yml配置
redis:
host: localhost # 默認localhost,需要遠程服務器需要修改
port: 6379 # 默認6379,如果不一致需要修改
database: 0 # 代表連接的數據庫索引,默認為0,
單元測試:
@RunWith(SpringJUnit4ClassRunner.class)
//重點是加入@SpringBootTest注解,屬性classes用于加載引導類
@SpringBootTest(classes = MyBootApplication.class)
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void redisTest() {
System.out.println("=================================================");
redisTemplate.opsForValue().set("superMan", "IronMan");
System.out.println(redisTemplate.opsForValue().get("superMan"));
redisTemplate.opsForList().leftPushAll("Color", "紅", "橙", "黃");
List color = redisTemplate.opsForList().range("Color", 0, 2);
for (Object o : color) {
System.out.println("Color List:" + o);
}
}
}
報錯
Q:Error:java: 無效的源發行版: 8
A:這是因為模塊的target bytecode version和實際的編譯器版本不一致所導致的錯誤,因此要對idea中的project structure 進行 jdk版本設置。
擴展
散列表
散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數,存放記錄的數組叫做散列表 。
redis常見性能問題和解決方案
- (1) Master最好不要做任何持久化工作,如RDB內存快照和AOF日志文件
- (2) 如果數據比較重要,某個Slave開啟AOF備份數據,策略設置為每秒同步一次
- (3) 為了主從復制的速度和連接的穩定性,Master和Slave最好在同一個局域網內
- (4) 盡量避免在壓力很大的主庫上增加從庫
- (5) 主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即:Master <- Slave1 <- Slave2 <- Slave3...
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1做Master,其他不變。
MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據
相關知識:redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。redis 提供 6種數據淘汰策略:
- voltile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
- volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
- volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
- allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
- allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
- no-enviction(驅逐):禁止驅逐數據
Redis 常見的性能問題都有哪些?如何解決?
- 1).Master寫內存快照,save命令調度rdbSave函數,會阻塞主線程的工作,當快照比較大時對性能影響是非常大的,會間斷性暫停服務,所以Master最好不要寫內存快照。
- 2).Master AOF持久化,如果不重寫AOF文件,這個持久化方式對性能的影響是最小的,但是AOF文件會不斷增大,AOF文件過大會影響Master重啟的恢復速度。Master最好不要做任何持久化工作,包括內存快照和AOF日志文件,特別是不要啟用內存快照做持久化,如果數據比較關鍵,某個Slave開啟AOF備份數據,策略為每秒同步一次。
- 3).Master調用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會占大量的CPU和內存資源,導致服務load過高,出現短暫服務暫停現象。
- 4). Redis主從復制的性能問題,為了主從復制的速度和連接的穩定性,Slave和Master最好在同一個局域網內