宣告:本人已儘量將參照的地方註明來源,如有侵權,請聯繫,如有部分圖片無法顯示,請存取我的個人主頁
wget http://download.redis.io/releases/redis-6.0.6.tar.gz
tar xzf redis-6.0.6.tar.gz
cd redis-6.0.6
make
make: *** [all] 錯誤 2
yum -y install centos-release-scl
yum -y install devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils
scl enable devtoolset-7 bash
echo "source /opt/rh/devtoolset-7/enable" >>/etc/profile
make
暫無
src/redis-server
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-sN8nG7iy-1597237183693)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/202008031113294fayaqifdy3.png)]
組態檔位置/root/redis-6.0.6/redis.conf
開啓組態檔vim redis.conf
yum install -y vim
(未測試)更改redis系結的IP地址
shift + :
,輸入69,按enter
鍵,這裏建議修改爲0.0.0.0
,即是允許所有IP地址連線的意思set nu
可以顯示檔案行號更改密碼
protected-mode
設爲no
解決)重要幾個參數所在行號
參數名 | 參數解釋 | 所在行號 | 預設值 |
---|---|---|---|
bind | 系結的主機IP地址 | 69 | 127.0.0.1 |
protected-mode | 是否可以直接存取,開啓需設定bind ip或者設定存取密碼 | 88 | yes |
port | 指定Redis監聽埠,預設埠爲6379 | 92 | 6379 |
pidfile | 守護行程方式執行時,pid的值 | 244 | /var/run/redis_6379.pid |
loglevel | 日誌級別,有debug、verbose、notice、warning | 252 | notice |
logfile | 日誌檔案位置,預設爲標準輸出, | 257 | 「」 |
databases | 邏輯數據庫的數量,預設連線數據庫爲0號數據庫,可以使用SELECT 命令在連線上指定數據庫id | 272 | 16 |
save | save ,多長時間內,有多少次更新操作,就將數據同步到數據檔案,可以多個條件配合 | 304 | 多個 |
requirepass | 密碼 | 786 | foobared |
ps -ef|grep redis
kill -9 pid號
./redis-server /root/redis-6.0.6/redis.conf &
,注意在src的目錄下!!!/redis-server &
,&代表後臺執行
./redis-server 組態檔名
,例如:./redis-server
/etc/redis/6379.conf
ps aux|grep redis
使用自己的redis連線工具,這裏使用的是RedisView
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-somLO2PR-1597237183701)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200803143522hxgu1ad5g4k.png)]
注意:阿裡雲或者騰訊雲等需要開放安全組,也就是防火牆開放遠端連線ip和埠
使用redisbin,在windows命令列連線
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-UseSaIsx-1597237183703)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/202008031438462sj5kaqjefw.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-Nz3dLVxq-1597237183705)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200803144415pk5cujmpope.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-a2wyUqVB-1597237183707)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200803144618ykmn5xakuqn.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-vldv4kbE-1597237183708)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/202008031450131jhcajg5ljy.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-Dp0u21Ck-1597237183709)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200803145856mzq0aa12qkt.png)]
String
儲存簡單字串、複雜字串(xml、json)、數位(整數、浮點數)、二進制(圖片、音訊、視訊),最大不能超過512MHash
儲存結構化物件List
儲存字串型別的集合數據,List中的數據是有序可重複的,因此可以通過下標獲取一個或者一段數據Set
儲存字串型別的集合數據,Set中的數據是無序的且不可重複Sorted Set
儲存不可重複的字串數據,但是區別於Set的是,Sorted Set可以在儲存數據時手動設定一個排序值,以此作爲排序依據有16個庫,從0–15,預設是0號庫,庫的選擇:select 庫號;不同庫的數據不影響
select 0-15 選擇庫
flushall
清空整個redis伺服器數據,所有的數據庫全部清空
flushdb
清除當前庫
參考苟哥資料
命令 | 語法 | 用途 | 範例 |
---|---|---|---|
set | set 鍵 值 | 儲存一個鍵值對,鍵存在則覆蓋值 | set test 10 |
get | get 鍵 | 通過鍵取出對應的值,如果鍵不存在則返回null | get test |
getset | getset 鍵 值 | 先取出鍵對應的值,然後修改值 | getset test 10 20 |
incr | incr 鍵 | 將鍵對應值自增1 | ncr test |
decr | decr 鍵 | 將鍵對應值自減1 | decr test |
incrby | incrby 鍵 自增值 | 將該鍵對應的值自增指定數值 | incrby test 20 |
decrby | decrby 鍵 自減值 | 將該鍵對應的值自減指定數值 | decrby test 10 |
append | append 鍵 值 | 如果該鍵存在,則在該值得基礎上追加一段字串,如果不存在該鍵則新增一個鍵值對 | append test 66 |
127.0.0.1:6379> expire key 60 # 數據在 60s 後過期
(integer) 1
127.0.0.1:6379> setex key 60 value # 數據在 60s 後過期 (setex:[set] + [ex]pire)
OK
127.0.0.1:6379> ttl key # 檢視數據還有多久過期
(integer) 56
命令 | 語法 | 用途 | 範例 |
---|---|---|---|
hset | hset 鍵 屬性名 值 | 爲指定的鍵所對應的hash數據中的某個屬性賦值 | hset student name jack |
hmset | hset 鍵 屬性名1 值1 屬性名2 值2 。。。 | 向指定的鍵所對應的hash數據中一次儲存一個或者多個鍵值對數據 | |
hget | hget 鍵 屬性名 | 查詢指定鍵對應的hash數據中某個屬性的值 | hget student name 結果:jack |
hmget | hmget 鍵 屬性名1 屬性名2 。。。 | 查詢指定鍵對應的hash數據中一個或多個鍵值對的值 | |
hdel | hdel 鍵 屬性名1 屬性名2 。。。 | 刪除指定鍵對應的hash數據中的一個或者多個屬性 | lrange names 0 10 結果是names對應的集閤中0-10之間的數據,如果數據長度不足,則返回已有的數據,不會出現異常 |
hexists | hexists 鍵 屬性 | 判斷指定鍵中是否存在某個屬性,返回1表示存在,0表示不存在 | hexists student name |
hlen | hlen 鍵 | 返回指定鍵對應的hash數據的屬性個數 | |
hkeys | hkeys 鍵 | 返回指定鍵對應的hash數據中的所有屬性名稱 | |
hvals | hvals 鍵 | 返回指定鍵對應的hash數據中的所有屬性值 | |
hincrby | hincrby 鍵 屬性名稱 增量 | 將指定鍵對應的屬性值自增增量的值 | hincrby student age 10 age的值在原本的基礎上+10 |
命令 | 語法 | 用途 | 範例 |
---|---|---|---|
lpush | lpush 鍵 值1 值2… | 在指定的鍵所對應的list的頭部插入所有的values,鍵不存在則新增 | lpush names jack rose 集閤中最前的兩個數據是rose jack |
rpush | rpush 鍵 值1 值2… | 在指定的鍵所對應的list的尾部插入所有的values,鍵不存在則新增 | rpush names jack rose 集閤中最後的兩個數據是jack rose |
lrange | lrange 鍵 下標1 下標2 | 查詢從下標1到下標2之間的數據,第一個數據下標爲0,下標可以爲負數,-1表示倒數第一個數據,-2表示倒數第二個數據,以此類推 | lrange names 0 10 結果是names對應的集閤中0-10之間的數據,如果數據長度不足,則返回已有的數據,不會出現異常 |
lpushx | lpushx鍵 值1 | 在指定的鍵存在的情況下,將所有的數據插入到集合的頭部 | lpushx names jack rose 集閤中最前的兩個數據是rose jack |
rpushx | rpushx鍵 值1 | 在指定的鍵存在的情況下,將所有的數據插入到集合的尾部 | rpush names jack rose 集閤中最後的兩個數據是jack rose |
lpop | lpop 鍵 | 將該鍵對應的集閤中的第一個數據取出,取出之後第一個數據就從集閤中移除 | lpop names 結果:取出並移除第一個數據 |
rpop | rpop鍵 | 將該鍵對應的集閤中的最後一個個數據取出,取出之後數據就從集閤中移除 | rpop names 結果:取出並移除最後一個數據 |
rpush/lpop
實現佇列127.0.0.1:6379> rpush myList value1 # 向 list 的頭部(右邊)新增元素
(integer) 1
127.0.0.1:6379> rpush myList value2 value3 # 向list的頭部(最右邊)新增多個元素
(integer) 3
127.0.0.1:6379> lpop myList # 將 list的尾部(最左邊)元素取出
"value1"
127.0.0.1:6379> lrange myList 0 1 # 檢視對應下標的list列表, 0 爲 start,1爲 end
1) "value2"
2) "value3"
127.0.0.1:6379> lrange myList 0 -1 # 檢視列表中的所有元素,-1表示倒數第一
1) "value2"
2) "value3"
rpush/rpop
實現棧127.0.0.1:6379> rpush myList2 value1 value2 value3
(integer) 3
127.0.0.1:6379> rpop myList2 # 將 list的頭部(最右邊)元素取出
"value3"
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-05MyqCrX-1597237183711)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200803183839vpelopqdzbh.png)]
lrange
檢視對應下標範圍的列表元素127.0.0.1:6379> rpush myList value1 value2 value3
(integer) 3
127.0.0.1:6379> lrange myList 0 1 # 檢視對應下標的list列表, 0 爲 start,1爲 end
1) "value1"
2) "value2"
127.0.0.1:6379> lrange myList 0 -1 # 檢視列表中的所有元素,-1表示倒數第一
1) "value1"
2) "value2"
3) "value3"
通過 lrange
命令,你可以基於 list 實現分頁查詢,效能非常高!
llen
檢視鏈表長度127.0.0.1:6379> llen myList
(integer) 3
命令 | 語法 | 用途 | 範例 |
---|---|---|---|
sadd | add 鍵 值1 值2… | 在指定的鍵對應的set集閤中儲存一個或多個數據 | sadd names jack tom 集閤中最前的兩個數據是rose jack |
smembers | smembers鍵 | 查詢指定鍵的Set集閤中儲存的所有數據 | smembers names |
scard | scard鍵 | 查詢指定鍵的Set集閤中儲存的數據個數 | scard names |
sismember | sismembe 鍵 值 | 判斷值是否是指定鍵對應的Set集閤中的成員,返回1表示是,0表示否 | sismember names jack |
srem | srem鍵 值1 值2… | 刪除指定鍵對應的Set集閤中的一個或多個數據 | srem names jack |
spop | spop鍵 count | 隨機刪除並返回指定鍵對應的Set集閤中的1個或多個數據,數量由count決定,但是在某些版本中count不支援,不提供count時預設count爲1 | spop numbers |
srandmember | srandmember鍵 count | 隨機返回指定鍵對應的Set集閤中的1個或多個數據,數量由count決定,不提供count時預設count爲1 | srandmember names 2 隨機返回names集閤中的2個數據 |
smove | smove 鍵1 鍵2 值 | 將鍵1對應集閤中的指定數據移動到鍵2的集閤中 | smove names1 names2 jack |
sdiff | sdiff 鍵1 鍵2 | 返回鍵1的集閤中在鍵2的集閤中不存在的數據,也就是求鍵1集合在鍵2集閤中的差集 | sdiff names1 names2 |
sdiffstore | sdiffstore 鍵1 鍵2 鍵3 | 將鍵2集合在鍵3中的差集儲存到鍵1的集閤中 | sdiffstore names names1 names2 |
sinter | sinter 鍵1 鍵2 | 返回鍵1集閤中在鍵2集閤中也存在的數據,也就是求鍵1集合和鍵2集合的交集 | sinter names1 names2 |
sinterstore | sinterstore 鍵1 鍵2 鍵3 | 將鍵2集合在鍵3中的交集儲存到鍵1的集閤中 | sinterstore names names1 names2 |
sunion | sunion 鍵1 鍵2 | 返回鍵1集合和鍵2集合的並集 | sunion names1 names2 |
sunionstore | sunion 鍵1 鍵2 鍵3 | 將鍵2集合和鍵3集合的並集儲存到鍵1集閤中 | sunionstore names names1 names2 |
命令 | 語法 | 用途 | 範例 |
---|---|---|---|
zadd | zadd 鍵 score value score value … | 向指定鍵對應的集閤中新增數據,score爲排序值,可以是整數或小數。value爲值 | zadd names 1 zhangsan 2 lisi |
zcard | zcard鍵 | 返回指定鍵對應的集閤中的數據總數 | zcard names |
zcount | zcount 鍵 min max | 查詢指定鍵的集閤中排序值在min和max之間的數據個數 | zcount names 1 5 |
zrange | zrange鍵 start stop | 返回指定鍵對應的集閤中排序序號(非排序值)在start和stop之間的數據,序號從0開始,數據會升序排列 | zrange names jack |
zrank | zrank 鍵 值 | 返回指定鍵對應的集閤中某個值得排序序號 | zrank names jack |
zrem | zrem 鍵1 值1 值2 | 移除指定鍵對應的Set集閤中的1個或多個值 | zrem names1 jack |
zremrangebyrank | zremrangebyrank 鍵 start stop | 按照排序序號移除多個成員 | zremrangebyrank names 0 2 |
zremrangebyscore | zremrangebyscore鍵 min max | 按照排序值移除多個成員 | zremrangebyscore names 1 2 |
雖然redis是單執行緒,但是可以同時有多個用戶端存取,每個用戶端會有一個執行緒。用戶端存取之間存在競爭,redis裏面只有單個命令是執行的。比如set,get。每執行一個命令都需要用戶端來競爭,所以可能出現併發問題,如果你希望把一組命令執行的結果作爲整體,要麼全部成功,要麼失敗,就必須用鎖,或者事務
開啓:multi
127.0.0.1:6379> multi
OK
提交:exec
127.0.0.1:6379> exec
OK
清除待執行佇列:discard
監聽:watch
類似樂觀鎖,
如果在watch
命令觀測一個key
之後,開啓事務後修改該key
.這個時候如果有其它連線修改了key
,則會導致事務執行失敗,在這個事務的其他操作也是失敗
exec
之後,watch
命令監控取消
watch
命令可以說是redis的事務功能最關鍵的運用了,在使用了watch
之後可以保證一定的原子性和數據安全
開啓事務之後的操作全部是在待執行佇列
中快取,並沒有真正執行,也就不存在事務內部的查詢要看到事務即將的更新,事務外部也不知道
Redis對單條命令是保證原子性(比如批次msetnx
命令),但是如果事務不保證原子性(一致性),就沒有回滾的概唸了.事務中任何命令的失敗,其餘命令任會執行
可以這麼說.Redis的以上兩個事務特徵幾乎可以認爲,redis沒有事務功能.更應該稱之爲命令的打包執行.
那麼爲什麼redis中要有事務?舉個例子:假設登錄的時候記錄登錄的ip(一條命令操作),接下再執行儲存使用者的登錄訊息操作(一條命令),假設獲取使用者的訊息需要在另外一個系統中獲取,我們無法保證100%獲取到.但是這兩步操作在我們程式業務功能設計中應該被認爲是登錄操作的單個功能起的影響.因爲獲取使用者的登錄訊息可能會失敗.那麼就沒必要記錄ip了.redis恰恰提供事務名佇列的清空功能
可以怎麼理解,如果你的(命令)操作步驟非常多,每一個命令都需要大量的其他非redis的操作才能 纔能保證接下來的業務進行,那麼就需要redis的事務佇列功能一步一步記錄命令,在整個工程中如果發生了意外則清空佇列,正常則提交
所以我們應該在我們的程式程式碼中保證一致性和隔離級別的功能而不是交給redis,方正redis的事務就是打包執行,任何利用是查詢設計的問題
在redis開啓事務的魅力multi
就可以知道,redis自己本身也沒有把這個功能稱之爲事務.正確的叫法是多命令
待執行佇列
中存在語法性錯誤,exec
提交之後,其他正確命令也會被執行,這是單單的錯誤命令拋出異常127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name li si #錯誤的命令
QUEUED
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> exec
1) (error) ERR syntax error
2) OK
如果是錯誤的命令名(比如
setnx
寫成setnn
,則不能稱之爲語法錯誤),如果在佇列中出現了類似錯誤,則整個佇列不成功
解決計算機關閉造成的記憶體數據丟失問題
redis預設採用此快照方式對數據進行持久化操作
Redis 快照 是最簡單的 Redis 永續性模式。當滿足特定條件時,它將生成數據集的時間點快照,例如,如果先前的快照是在2分鐘前建立的,並且現在已經至少有 100 次新寫入,則將建立一個新的快照。此條件可以由使用者設定 Redis 範例來控制,也可以在執行時修改而無需重新啓動伺服器。快照作爲包含整個數據集的單個 .rdb
檔案生成。
快照不是很持久。如果執行 Redis 的計算機停止執行,電源線出現故障或者您 kill -9
的範例意外發生,則寫入 Redis 的最新數據將丟失。儘管這對於某些應用程式可能不是什麼大問題,但有些使用案例具有充分的耐用性,在這些情況下,快照並不是可行的選擇。
AOF(Append Only File - 僅追加檔案) 它的工作方式非常簡單:每次執行 修改記憶體 中數據集的寫操作時,都會 記錄 該操作。假設 AOF 日誌記錄了自 Redis 範例建立以來 所有的修改性指令序列,那麼就可以通過對一個空的 Redis 範例 順序執行所有的指令,也就是 「重放」,來恢復 Redis 當前範例的記憶體數據結構的狀態
Redis 在長期執行的過程中,AOF 的日誌會越變越長。如果範例宕機重新啓動,重放整個 AOF 日誌會非常耗時,導致長時間 Redis 無法對外提供服務。所以需要對 AOF 日誌 「瘦身」。
Redis 提供了
bgrewriteaof
指令用於對 AOF 日誌進行瘦身。其 原理 就是 開闢一個子進程 對記憶體進行 遍歷 轉換成一系列 Redis 的操作指令,序列化到一個新的 AOF 日誌檔案 中。序列化完畢後再將操作期間發生的 增量 AOF 日誌 追加到這個新的 AOF 日誌檔案中,追加完畢後就立即替代舊的 AOF 日誌檔案了,瘦身工作就完成了。
AOF 日誌是以檔案的形式存在的,當程式對 AOF 日誌檔案進行寫操作時,實際上是將內容寫到了內核爲檔案描述符分配的一個記憶體快取中,然後內核會非同步將髒數據刷回到磁碟的。
就像我們 上方第四步 描述的那樣,我們需要藉助
glibc
提供的fsync(int fd)
函數來講指定的檔案內容 強制從內核快取刷到磁碟。但 「強制開車」 仍然是一個很消耗資源的一個過程,需要 「節制」!通常來說,生產環境的伺服器,Redis 每隔 1s 左右執行一次fsync
操作就可以了。Redis 同樣也提供了另外兩種策略,一個是 永不
fsync
,來讓操作系統來決定合適同步磁碟,很不安全,另一個是 來一個指令就fsync
一次,非常慢。但是在生產環境基本不會使用,瞭解一下即可。
cat redis.conf | grep -v "#" | grep -v "^$" > redis7379.conf
命令將組態檔的註釋去掉並放入另外一個組態檔bind
0.0.00
port
7379
pidfile
/var/run/redis_7379.pid
logfile
「/root/redis-6.0.6/redis_7379.log」
appendonly
yes
appendfilename
「appendonly7379.aof」
appendfsync
everysec
啓動多個redis,啓動預設都是爲主節點
#!/bin/bash
./../src/redis-server /root/redis-6.0.6/config/redis7379.conf &
./../src/redis-server /root/redis-6.0.6/config/redis7380.conf &
./../src/redis-server /root/redis-6.0.6/config/redis7381.conf &
將主節點變成從節點,使用slaveof
命令
PS D:\soft_green_store\redisbin64> ./redis-cli.exe -p 7380 -h 120.26.173.108 -a jungle123456
slaveof 120.26.173.108 7380
requirepass
要求密碼驗證的情況下,主庫已設定則從庫需額外在組態檔中加上masterauth 主庫密碼
參數纔可以複製主庫的數據[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-BipfMlQQ-1597237183713)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200805142920acfad2ccmfu.png)]info replication
可以檢視redis相關狀態資訊搭建完成
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-PyhzxUjp-1597237183716)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200805144824jwhpd4equfv.png)]
複製幾分哨兵的組態檔出來
port 26379 #哨兵埠
daemonize yes #後臺守護
logfile "/root/redis-6.0.6/config/sentinel_log/26379.log" #日誌檔案
#mymaster這個名字是自己給的別名,還是系統預設?? 名字監聽ip+埠 選舉次數要到達2次
sentinel monitor mymaster 120.26.173.108 7379 2
sentinel auth-pass mymaster jungle123456 #監聽密碼
sentinel down-after-milliseconds mymaster 10000 #監聽服務GG等待時間
#應該還應該設定哨兵的密碼!!!生產環境
增加bash命令
#!/bin/bash
#啓動redis主從
./../src/redis-server /root/redis-6.0.6/config/redis7379.conf &
./../src/redis-server /root/redis-6.0.6/config/redis7380.conf &
./../src/redis-server /root/redis-6.0.6/config/redis7381.conf &
#啓動哨兵,哨兵啓動後,哨兵組態檔,還會發現出現了一些變化
./../src/redis-server /root/redis-6.0.6/config/sentin1.conf --sentinel
./../src/redis-server /root/redis-6.0.6/config/sentin2.conf --sentinel
./../src/redis-server /root/redis-6.0.6/config/sentin3.conf --sentinel
測試
使用 redis-cil
工具連線哨兵節點,並執行 info Sentinel
命令來檢視是否已經在監視主節點了:
PS D:\soft_green_store\redisbin64> ./redis-cli.exe -p 26379 -h 120.26.173.108
redis 120.26.173.108:26379> info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=120.26.173.108:7379,slaves=0,sentinels=3
上面列印的資訊顯示出,一個主節點下並沒有子slaves節點,說明啓動的三個redis服務,另外兩個並沒有成爲子服務,因爲之前是通過啓動後再通過命令來將主節點變成子節點,這裏覺得太麻煩,果斷修改組態檔,加上slaveof 120.26.173.108 7379
,再重新啓動啓動,就一切ok了,全部設定如下:
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes
masterauth jungle123456
slaveof 120.26.173.108 7379
再測試kill掉主節點後的變化
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=120.26.173.108:7380,slaves=2,sentinels=3
redis 120.26.173.108:26379>
但同時還可以發現,哨兵節點認爲新的主節點仍然有兩個從節點 (上方 slaves=2),這是因爲哨兵在將 6381
切換成主節點的同時,將 6379
節點置爲其從節點。雖然 6379
從節點已經掛掉,但是由於 哨兵並不會對從節點進行客觀下線,因此認爲該從節點一直存在。當 6379
節點重新啓動後,會自動變成 6381
節點的從節點。
另外,在故障轉移的階段,哨兵和主從節點的組態檔都會被改寫:
slaveof
設定的變化,新的主節點沒有了 slaveof
設定,其從節點則 slaveof
新的主節點。那麼,問題就來了,3個哨兵,不小心掛了兩個,選舉又要求有2個,這樣的情況又如何解決呢?
搜尋了一下,沒人提這個東西,是需要哨兵之間搭一個叢集,還是這個方案沒人用,所以沒人care。Q。。。AQ。。。
注:本文很多理論內容都是來自這裏,特別是下面 下麪的內容,幾乎一模一樣,主要目的是防止原文消失QAQ
上圖 展示了 Redis Cluster 典型的架構圖,叢集中的每一個 Redis 節點都 互相兩兩相連,用戶端任意 直連 到叢集中的 任意一臺,就可以對其他 Redis 節點進行 讀寫 的操作。
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-ApjFrNbY-1597237183717)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/202008051750570iomfselny4.png)]
Redis 叢集中內建了 16384
個雜湊槽。當用戶端連線到 Redis 叢集之後,會同時得到一份關於這個 叢集的設定資訊,當用戶端具體對某一個 key
值進行操作時,會計算出它的一個 Hash 值,然後把結果對 16384
求餘數,這樣每個 key
都會對應一個編號在 0-16383
之間的雜湊槽,Redis 會根據節點數量 大致均等 的將雜湊槽對映到不同的節點。
再結合叢集的設定資訊就能夠知道這個 key
值應該儲存在哪一個具體的 Redis 節點中,如果不屬於自己管,那麼就會使用一個特殊的 MOVED
命令來進行一個跳轉,告訴用戶端去連線這個節點以獲取數據:
GET x
-MOVED 3999 127.0.0.1:6381
MOVED
指令第一個參數 3999
是 key
對應的槽位編號,後面是目標節點地址,MOVED
命令前面有一個減號,表示這是一個錯誤的訊息。用戶端在收到 MOVED
指令後,就立即糾正原生的 槽位對映表,那麼下一次再存取 key
時就能夠到正確的地方去獲取了。
bgsave
和 bgrewriteaof
的 fork
操作可能導致主進程阻塞,主從環境下主機切換時可能導致從節點長時間無法提供服務,全量複製階段主節點的複製緩衝區可能溢位……首先我們找一個地方建立一個名爲 redis-cluster
的目錄:
mkdir -p ~/Desktop/redis-cluster
然後按照上面的方法,建立六個組態檔,分別命名爲:redis_7000.conf
/redis_7001.conf
…redis_7005.conf
,然後根據不同的埠號修改對應的埠值就好了:
# 後臺執行
daemonize yes
# 埠號
port 7000
# 爲每一個叢集節點指定一個 pid_file
pidfile ~/Desktop/redis-cluster/redis_7000.pid
# 啓動叢集模式
cluster-enabled yes
# 每一個叢集節點都有一個組態檔,這個檔案是不能手動編輯的。確保每一個叢集節點的組態檔不通
cluster-config-file nodes-7000.conf
# 叢集節點的超時時間,單位:ms,超時後叢集會認爲該節點失敗
cluster-node-timeout 5000
# 最後將 appendonly 改成 yes(AOF 持久化)
appendonly yes
protected-mode false
記得把對應上述組態檔中根埠對應的設定都修改掉 (port/ pidfile/ cluster-config-file)。
Jungle:
sed -i "s/7001/7006/g"
grep 「7001」 -rl ./redis_7006.conf``可以批次將檔案內的內容替換redis-server ~/Desktop/redis-cluster/redis_7000.conf
redis-server ~/Desktop/redis-cluster/redis_7001.conf
redis-server ~/Desktop/redis-cluster/redis_7002.conf
redis-server ~/Desktop/redis-cluster/redis_7003.conf
redis-server ~/Desktop/redis-cluster/redis_7004.conf
redis-server ~/Desktop/redis-cluster/redis_7005.conf
然後執行 ps -ef | grep redis
檢視是否啓動成功:
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-8Ux1FPLk-1597237183718)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200805174624m2ykqlzafny.png)]
可以看到 6
個 Redis 節點都以叢集的方式成功啓動了,但是現在每個節點還處於獨立的狀態,也就是說它們每一個都各自成了一個叢集,還沒有互相聯繫起來,我們需要手動地把他們之間建立起聯繫。
執行下列命令:
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
Jungle:
執行了
./../../src/redis-cli --cluster create --cluster-replicas 1 120.26.173.108:7000 120.26.173.108:7001 120.26.173.108:7002 120.26.173.108:7003 120.26.173.108:7004 120.26.173.108:7005
出現[ERR] Node 120.26.173.108:7000 DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients一大串紅色。
我估計就是因爲組態檔沒有設定protected-mode false
,系統預設給了true,這時候可以選擇給個false,或者給個密碼
再次執行,一直出現Waiting for the cluster to join...............................................
原因是埠沒有放行,這裏使用的是7001到7005,那麼7001-7005及17001-17005都要放行
這裏稍微解釋一下這個 --replicas 1
的意思是:我們希望爲叢集中的每個主節點建立一個從節點。
觀察控制檯輸出:
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-60tiIHbZ-1597237183719)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200805174704wnixsrzjumr.png)]
看到 [OK]
的資訊之後,就表示叢集已經搭建成功了,可以看到,這裏我們正確地建立了三主三從的叢集。
我們先使用 redic-cli
任意連線一個節點:
redis-cli -c -h 127.0.0.1 -p 7000
127.0.0.1:7000>
-c
表示叢集模式;-h
指定 ip 地址;-p
指定埠。然後隨便 set
一些值觀察控制檯輸入:
127.0.0.1:7000> SET name wmyskxz
-> Redirected to slot [5798] located at 127.0.0.1:7001
OK
127.0.0.1:7001>
可以看到這裏 Redis 自動幫我們進行了 Redirected
操作跳轉到了 7001
這個範例上。
我們再使用 cluster info
(檢視叢集資訊) 和 cluster nodes
(檢視節點列表) 來分別看看:(任意節點輸入均可)
127.0.0.1:7001> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_ping_sent:1365
cluster_stats_messages_pong_sent:1358
cluster_stats_messages_meet_sent:4
cluster_stats_messages_sent:2727
cluster_stats_messages_ping_received:1357
cluster_stats_messages_pong_received:1369
cluster_stats_messages_meet_received:1
cluster_stats_messages_received:2727
127.0.0.1:7001> CLUSTER NODES
56a04742f36c6e84968cae871cd438935081e86f 127.0.0.1:7003@17003 slave 4ec8c022e9d546c9b51deb9d85f6cf867bf73db6 0 1584428884000 4 connected
4ec8c022e9d546c9b51deb9d85f6cf867bf73db6 127.0.0.1:7000@17000 master - 0 1584428884000 1 connected 0-5460
e2539c4398b8258d3f9ffa714bd778da107cb2cd 127.0.0.1:7005@17005 slave a3406db9ae7144d17eb7df5bffe8b70bb5dd06b8 0 1584428885222 6 connected
d31cd1f423ab1e1849cac01ae927e4b6950f55d9 127.0.0.1:7004@17004 slave 236cefaa9cdc295bc60a5bd1aed6a7152d4f384d 0 1584428884209 5 connected
236cefaa9cdc295bc60a5bd1aed6a7152d4f384d 127.0.0.1:7001@17001 myself,master - 0 1584428882000 2 connected 5461-10922
a3406db9ae7144d17eb7df5bffe8b70bb5dd06b8 127.0.0.1:7002@17002 master - 0 1584428884000 3 connected 10923-16383
127.0.0.1:7001>
雜湊取餘分割區思路非常簡單:計算 key
的 hash 值,然後對節點數量進行取餘,從而決定數據對映到哪個節點上。
不過該方案最大的問題是,當新增或刪減節點時,節點數量發生變化,系統中所有的數據都需要 重新計算對映關係,引發大規模數據遷移。
一致性雜湊演算法將 整個雜湊值空間 組織成一個虛擬的圓環,範圍是 [0 , 232-1],對於每一個數據,根據 key
計算 hash 值,確數據在環上的位置,然後從此位置沿順時針行走,找到的第一臺伺服器就是其應該對映到的伺服器:
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-LRoMwy5m-1597237183719)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200805174731njzsdwdzequ.png)]
與雜湊取餘分割區相比,一致性雜湊分割區將 增減節點的影響限制在相鄰節點。以上圖爲例,如果在 node1
和 node2
之間增加 node5
,則只有 node2
中的一部分數據會遷移到 node5
;如果去掉 node2
,則原 node2
中的數據只會遷移到 node4
中,只有 node4
會受影響。
一致性雜湊分割區的主要問題在於,當 節點數量較少 時,增加或刪減節點,對單個節點的影響可能很大,造成數據的嚴重不平衡。還是以上圖爲例,如果去掉 node2
,node4
中的數據由總數據的 1/4
左右變爲 1/2
左右,與其他節點相比負載過高。
該方案在 一致性雜湊分割區的基礎上,引入了 虛擬節點 的概念。Redis 叢集使用的便是該方案,其中的虛擬節點稱爲 槽(slot)。槽是介於數據和實際節點之間的虛擬概念,每個實際節點包含一定數量的槽,每個槽包含雜湊值在一定範圍內的數據。
在使用了槽的一致性雜湊分割區中,槽是數據管理和遷移的基本單位。槽 解耦 了 數據和實際節點 之間的關係,增加或刪除節點對系統的影響很小。仍以上圖爲例,系統中有 4
個實際節點,假設爲其分配 16
個槽(0-15);
如果此時刪除 node2
,只需要將槽 4-7 重新分配即可,例如槽 4-5 分配給 node1
,槽 6 分配給 node3
,槽 7 分配給 node4
;可以看出刪除 node2
後,數據在其他節點的分佈仍然較爲均衡。
叢集的建立離不開節點之間的通訊,例如我們上訪在 快速體驗 中剛啓動六個叢集節點之後通過 redis-cli
命令幫助我們搭建起來了叢集,實際上背後每個叢集之間的兩兩連線是通過了 CLUSTER MEET <ip> <port>
命令發送 MEET
訊息完成的,下面 下麪我們展開詳細說說。
在 哨兵系統 中,節點分爲 數據節點 和 哨兵節點:前者儲存數據,後者實現額外的控制功能。在 叢集 中,沒有數據節點與非數據節點之分:所有的節點都儲存數據,也都參與叢集狀態的維護。爲此,叢集中的每個節點,都提供了兩個 TCP 埠:
7000
節點的叢集埠爲 17000
。叢集埠只用於節點之間的通訊,如搭建叢集、增減節點、故障轉移等操作時節點間的通訊;不要使用用戶端連線叢集介面。爲了保證叢集可以正常工作,在設定防火牆時,要同時開啓普通埠和叢集埠。節點間通訊,按照通訊協定可以分爲幾種型別:單對單、廣播、Gossip 協定等。重點是廣播和 Gossip 的對比。
叢集中的節點採用 固定頻率(每秒10次) 的 定時任務 進行通訊相關的工作:判斷是否需要發送訊息及訊息型別、確定接收節點、發送訊息等。如果叢集狀態發生了變化,如增減節點、槽狀態變更,通過節點間的通訊,所有節點會很快得知整個叢集的狀態,使叢集收斂。
節點間發送的訊息主要分爲 5
種:meet 訊息
、ping 訊息
、pong 訊息
、fail 訊息
、publish 訊息
。不同的訊息型別,通訊協定、發送的頻率和時機、接收節點的選擇等是不同的:
CLUSTER MEET
命令時,會向新加入的節點發送 MEET
訊息,請求新節點加入到當前叢集;新節點收到 MEET 訊息後會回覆 回復一個 PONG
訊息。PING
訊息,接收者收到訊息後會回覆 回復一個 PONG
訊息。PING 訊息的內容是自身節點和部分其他節點的狀態資訊,作用是彼此交換資訊,以及檢測節點是否線上。PING
訊息使用 Gossip 協定發送,接收節點的選擇兼顧了收斂速度和頻寬成本,具體規則如下:(1)隨機找 5 個節點,在其中選擇最久沒有通訊的 1 個節點;(2)掃描節點列表,選擇最近一次收到 PONG
訊息時間大於 cluster_node_timeout / 2
的所有節點,防止這些節點長時間未更新。PONG
訊息封裝了自身狀態數據。可以分爲兩種:第一種 是在接到 MEET/PING
訊息後回覆 回復的 PONG
訊息;第二種 是指節點向叢集廣播 PONG
訊息,這樣其他節點可以獲知該節點的最新資訊,例如故障恢復後新的主節點會廣播 PONG
訊息。FAIL
狀態時,會向叢集廣播這一 FAIL
訊息;接收節點會將這一 FAIL
訊息儲存起來,便於後續的判斷。PUBLISH
命令後,會先執行該命令,然後向叢集廣播這一訊息,接收節點也會執行該 PUBLISH
命令。節點需要專門的數據結構來儲存叢集的狀態。所謂叢集的狀態,是一個比較大的概念,包括:叢集是否處於上線狀態、叢集中有哪些節點、節點是否可達、節點的主從狀態、槽的分佈……
節點爲了儲存叢集狀態而提供的數據結構中,最關鍵的是 clusterNode
和 clusterState
結構:前者記錄了一個節點的狀態,後者記錄了叢集作爲一個整體的狀態。
clusterNode
結構儲存了 一個節點的當前狀態,包括建立時間、節點 id、ip 和埠號等。每個節點都會用一個 clusterNode
結構記錄自己的狀態,併爲叢集內所有其他節點都建立一個 clusterNode
結構來記錄節點狀態。
下面 下麪列舉了 clusterNode
的部分欄位,並說明了欄位的含義和作用:
typedef struct clusterNode {
//節點建立時間
mstime_t ctime;
//節點id
char name[REDIS_CLUSTER_NAMELEN];
//節點的ip和埠號
char ip[REDIS_IP_STR_LEN];
int port;
//節點標識:整型,每個bit都代表了不同狀態,如節點的主從狀態、是否線上、是否在握手等
int flags;
//設定紀元:故障轉移時起作用,類似於哨兵的設定紀元
uint64_t configEpoch;
//槽在該節點中的分佈:佔用16384/8個位元組,16384個位元;每個位元對應一個槽:位元值爲1,則該位元對應的槽在節點中;位元值爲0,則該位元對應的槽不在節點中
unsigned char slots[16384/8];
//節點中槽的數量
int numslots;
…………
} clusterNode;
除了上述欄位,clusterNode
還包含節點連線、主從複製、故障發現和轉移需要的資訊等。
clusterState
結構儲存了在當前節點視角下,叢集所處的狀態。主要欄位包括:
typedef struct clusterState {
//自身節點
clusterNode *myself;
//設定紀元
uint64_t currentEpoch;
//叢集狀態:線上還是下線
int state;
//叢集中至少包含一個槽的節點數量
int size;
//雜湊表,節點名稱->clusterNode節點指針
dict *nodes;
//槽分佈資訊:陣列的每個元素都是一個指向clusterNode結構的指針;如果槽還沒有分配給任何節點,則爲NULL
clusterNode *slots[16384];
…………
} clusterState;
除此之外,clusterState
還包括故障轉移、槽遷移等需要的資訊。
設定
閱讀文章
概念
https://blog.csdn.net/nsrainbow/article/details/49032337
文章這裏設定不錯
bind:0.0.0.0(指定存取的網絡卡,預設爲127.0.01只能本機存取,可以將此項改爲0.0.0.0或本機IP,或者直接註釋掉此項。)
protected-mode:no (是否開啓保護模式,開啓後只能本機存取。此項預設爲yes,需要設定爲no。)
port:7000(服務執行埠,如果6個節點執行在同一臺機器上,每個節點的埠應不相同。)
requirepass:123456(存取密碼,設定爲需要的密碼。建議每個節點密碼相同。)
masterauth:123456(主節點的密碼,當從節點從主節點同步數據時,需要提供主節點的密碼。一般與存取密碼相同。)
cluster-enabled :yes(是否開啓cluster模式,預設爲no,需要設定爲yes。)
cluster-config-file:nodes.conf (儲存cluster中每個節點資訊的檔案,該檔案會自動生成,這裏設定的是檔案儲存的位置。)
cluster-node-timeout:5000(超時多長時間後判斷節點掛掉。)
appendonly:yes(開啓AOF持久化)
大量請求的key不存在快取中,導致請求全部落在數據庫
參數校驗
ID校驗
郵箱格式不對
參考文章
參考文章
Validated代表去實體類校驗
<1> 參數 Foo 前需要加上 @Validated 註解,表明需要 spring 對其進行校驗,而校驗的資訊會存放到其後的 BindingResult 中。注意,必須相鄰,如果有多個參數需要校驗,形式可以如下。foo(@Validated Foo foo, BindingResult fooBindingResult ,@Validated Bar bar, BindingResult barBindingResult); 即一個校驗類對應一個校驗結果。
<2> 校驗結果會被自動填充,在 controller 中可以根據業務邏輯來決定具體的操作,如跳轉到錯誤頁面。
#JSR 提供的校驗註解
@Null 被註釋的元素必須爲 null
@NotNull 被註釋的元素必須不爲 null
@AssertTrue 被註釋的元素必須爲 true
@AssertFalse 被註釋的元素必須爲 false
@Min(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@Max(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@DecimalMin(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@DecimalMax(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@Size(max=, min=) 被註釋的元素的大小必須在指定的範圍內
@Digits (integer, fraction) 被註釋的元素必須是一個數字,其值必須在可接受的範圍內
@Past 被註釋的元素必須是一個過去的日期
@Future 被註釋的元素必須是一個將來的日期
@Pattern(regex=,flag=) 被註釋的元素必須符合指定的正則表達式
#Hibernate Validator
@NotBlank(message =) 驗證字串非 null,且長度必須大於 0
@Email 被註釋的元素必須是電子郵箱地址
@Length(min=,max=) 被註釋的字串的大小必須在指定的範圍內
@NotEmpty 被註釋的字串的必須非空
@Range(min=,max=,message=) 被註釋的元素必須在合適的範圍內
總結:
在springboot中,對於@RequestParam的非實體類參數進行校驗,需要在類上加上@Validated註解,BindingRequest參數必須僅跟着實體類參數校驗,不能離太遠,@validate註解後如果不跟BindingRequest參數,則會拋出異常,不會進入方法內部,其實我也知道,我以後可能不會看這個,但是就是想寫一寫QAQ…
快取和數據庫都沒有可以設定過期時間
set key value EX 10086
但是隻能解決key變化不頻繁的情況,如要使用此方法,儘量將key的過期時間設定短一點,比如1分鐘
注:key的命名:表名:主鍵名:主鍵值
public Object getObjectInclNullById(Integer id) {
// 從快取中獲取數據
Object cacheValue = cache.get(id);
// 快取爲空
if (cacheValue == null) {
// 從數據庫中獲取
Object storageValue = storage.get(key);
// 快取空物件
cache.set(key, storageValue);
// 如果儲存數據爲空,需要設定一個過期時間(300秒)
if (storageValue == null) {
// 必須設定過期時間,否則有被攻擊的風險
cache.expire(key, 60 * 5);
}
return storageValue;
}
return cacheValue;
}
布隆過濾器
布隆過濾器是一個非常神奇的數據結構,通過它我們可以非常方便地判斷一個給定數據是否存在於海量數據中。我們需要的就是判斷 key 是否合法,有沒有感覺布隆過濾器就是我們想要找的那個「人」。
具體是這樣做的:把所有可能存在的請求的值都存放在布隆過濾器中,當使用者請求過來,先判斷使用者發來的請求的值是否存在於布隆過濾器中。不存在的話,直接返回請求參數錯誤資訊給用戶端,存在的話纔會走下面 下麪的流程。
具體參考另外一篇詳細文章
實際上,快取雪崩描述的就是這樣一個簡單的場景:快取在同一時間大面積的失效,後面的請求都直接落到了數據庫上,造成數據庫短時間內承受大量請求。 這就好比雪崩一樣,摧枯拉朽之勢,數據庫的壓力可想而知,可能直接就被這麼多請求弄宕機了。
舉個例子:系統的快取模組出了問題比如宕機導致不可用。造成系統的所有存取,都要走數據庫。
還有一種快取雪崩的場景是:有一些被大量存取數據(熱點快取)在某一時刻大面積失效,導致對應的請求直接落到了數據庫上。 這樣的情況,有下面 下麪幾種解決辦法:
舉個例子 :秒殺開始 12 個小時之前,我們統一存放了一批商品到 Redis 中,設定的快取過期時間也是 12 個小時,那麼秒殺開始的時候,這些秒殺的商品的存取直接就失效了。導致的情況就是,相應的請求直接就落到了數據庫上,就像雪崩一樣可怕。
針對 Redis 服務不可用的情況:
針對熱點快取失效的情況:
導包
<!--Redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
啓動器開啓快取,新增@EnableCaching
註解
新增組態檔
spring:
redis:
database: 0
host: 120.26.173.108
port: 7000
#password: jungle123456
#連線超時時間(毫秒)
timeout: 20000
jedis:
pool:
#連線池最大連線數(使用負值表示沒有限制)
max-active: 8
#連線池最大阻塞等待時間(使用負值表示沒有限制)
max-wait: 1
#連線池中的最大空閒連線
max-idle: 8
#連線池中的最小空閒連線
min-idle: 0
cluster:
nodes:
- 120.26.173.108:7000
- 120.26.173.108:7001
- 120.26.173.108:7002
- 120.26.173.108:7003
- 120.26.173.108:7004
- 120.26.173.108:7005
max-redirects: 3
設定一下redis序列化方式
/**
* Redis 快取快取管理器
* JdkSerializationRedisSerializer:
*
* GenericJackson2JsonRedisSerializer
*
* StringRedisSerializer
*
* GenericFastJsonRedisSerializer
*
* GenericFastJsonRedisSerializer,最好用,不報錯
* @author Jiangmanman
* @date 2020/08/06
*/
@Configuration
public class RedisConfig {
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
//設定redis快取值的序列化方式,此處採用json方式序列化
redisCacheConfiguration =
redisCacheConfiguration.
serializeValuesWith(RedisSerializationContext.SerializationPair.
fromSerializer(new GenericFastJsonRedisSerializer()));
return redisCacheConfiguration;
}
}
在業務層層的查詢方法上新增@Cacheable(value = "快取數據的名稱空間名稱")
,將查詢的數據儲存到redis中,後續執行這個業務層方法會優先從快取中獲取數據。
在業務層的增刪改方法上新增@CacheEvict(value="快取數據的名稱空間名稱",allEntries = true)
註解,在執行增刪改時將快取數據刪除,下次查詢時會從數據庫查詢數據。
屬性詳細解釋如下
Cacheable
cacheNames:快取數據的名稱空間,可以用於區分不同的數據,其實該值就是快取數據鍵的字首。
key:定義快取數據的後綴,可以在同一個名稱空間下,對不同的數據進行更加細緻的拆分。在key中可以使用#參數名稱的方式用參數作爲key。
CacheEvict
cacheNames:需要清除的快取數據的名稱空間
allEntries:是否需要清空名稱空間中所有的數據
例如:
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-gkTJp9NY-1597237183720)(https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202008/20200806120440wktabda0dim.png)]
springboot整合redis叢集,組態檔IP地址爲伺服器公網ip,控制檯日誌報錯卻是伺服器內網ip連線不上.
問題原因:整合springboot之後,他會用任意節點通過cluster slots 命令去獲取叢集中糟點資訊,根據控制檯報錯返回所有節點資訊都是內網ip。因爲每個節點都是從自己的nodes.conf檔案中獲取cluster-config-file的地址。叢集第一次啓動後,會在
cd ./cluster/data/相對應的節點目錄下生成該檔案,開啓該檔案會發現cluster-config-file一行的ip地址是自身的內網ip.這是因爲生成時自己的的節點ip時通過網絡卡IP作爲地址的,由於雲伺服器網絡卡地址是內網,自然這裏的ip就是內網的IP地址了。
解決方案:
先殺死節點,修改每個節點的nodes.conf中的cluster-config-file,把內網ip改爲公網ip;再重新啓動。就OK了(後記:手動將cluster-config-file /root/redis-6.0.6/config/cluster/nodes-7000.conf
這個檔案裏面的內網IP變成公網IP,:
#改變命令,每一個都需要改
sed -i "s/172.16.62.141/120.26.173.108/g" `grep "172.16.62.141" -rl ./nodes-7005.conf`
#然後重新啓動
./../../src/redis-server /root/redis-6.0.6/config/cluster/redis_7004.conf
#天吶,要不要這麼麻煩!!!
)
每個組態檔加上 bind 0.0.0.0
重新啓動出現
[ERR] Node 120.26.173.108:7000 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
伺服器重新啓動前節點中儲存了節點設定以及數據備份檔案。重新啓動時節點以及數據資訊衝突,故無法重新啓動。
刪除節點設定(nodes.conf)以及數據備份檔案(dump.rdb、appendonly.aof)
清除各節點數據
2.1 連線進入各節點
Linux命令 ./redis-cli -h 192.168.25.133 -p 7001
2.2 清除節點數據
Linux命令 flushdb
偶也,完成所有步驟,springboot測試也成功,將redis的cluster設定備份一下,備份連線如下
鏈接: https://pan.baidu.com/s/17WQFF-X488Cvx7mEopAmRA 提取碼: yka1