7.11日學習打卡
目錄:
- 7.11日學習打卡
- 一. redis事務
- 事務的概念與ACID特性
- Redis事務三大特性
- Redis事務執行的三個階段
- Redis事務基本操作
- 二. redis集群
- 主從復制
- 主從復制環境搭建
- 主從復制原理剖析
- 哨兵監控
- 哨兵監控環境搭建
- 哨兵工作原理剖析
- 故障轉移
- Cluster模式
- Cluster模式搭建
- Cluster模式原理剖析
- Java操作Redis集群
一. redis事務
事務的概念與ACID特性
數據庫層面事務
在數據庫層面,事務是指一組操作,這些操作要么全都被成功執行,要么全都不執行。
數據庫事務的四大特性
- A:Atomic,原子性,將所有SQL作為原子工作單元執行,要么全部執行,要么全部不執行;
- C:Consistent,一致性,事務完成后,所有數據的狀態都是一致的,即A賬戶只要減去了100,B賬戶則必定加上了100;
- I:Isolation,隔離性,如果有多個事務并發執行,每個事務作出的修改必須與其他事務隔離;
- D:Duration,持久性,即事務完成后,對數據庫數據的修改被持久化存儲。
Redis事務
Redis事務是一組命令的集合,一個事務中的所有命令都將被序列化,按照一次性、順序性、排他性的執行一系列的命令。
Redis事務三大特性
- 單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷;
- 沒有隔離級別的概念:隊列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行,也就不存在”事務內的查詢要看到事務里的更新,在事務外查詢不能看到”。
- 不保證原子性:redis同一個事務中如果有一條命令執行失敗,其后的命令仍然會被執行,沒有回滾;
Redis事務執行的三個階段
- 開啟:以
MULTI
開始一個事務; - 入隊:將多個命令入隊到事務中,接到這些命令并不會立即執行,而是放到等待執行的事務隊列里面;
- 執行:由
EXEC
命令觸發事務;
Redis事務基本操作
Multi、Exec、discard
事務從輸入Multi
命令開始,輸入的命令都會依次壓入命令緩沖隊列中,并不會執行,直到輸入Exec
后,Redis會將之前的命令緩沖隊列中的命令依次執行。組隊過程中,可以通過discard
來放棄組隊。
例子
127.0.0.1:6379> set t1 1
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set id 12
QUEUED
127.0.0.1:6379(TX)> get id
QUEUED
127.0.0.1:6379(TX)> incr t1
QUEUED
127.0.0.1:6379(TX)> incr t1
QUEUED
127.0.0.1:6379(TX)> get t1
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) "12"
3) (integer) 2
4) (integer) 3
5) "3"
放棄事務
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set name z3
QUEUED
127.0.0.1:6379(TX)> set age 29
QUEUED
127.0.0.1:6379(TX)> incr t1
QUEUED
127.0.0.1:6379(TX)> DISCARD
OK
全體連坐
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set name z3
QUEUED
127.0.0.1:6379(TX)> get name
QUEUED
127.0.0.1:6379(TX)> incr t1
QUEUED
127.0.0.1:6379(TX)> get t1
QUEUED
127.0.0.1:6379(TX)> set email
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
注意:
命令集合中含有錯誤的指令(注意是語法錯誤),均連坐,全部失敗。
冤有頭,債有主
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set age 11
QUEUED
127.0.0.1:6379(TX)> incr t1
QUEUED
127.0.0.1:6379(TX)> set email abc@163.com
QUEUED
127.0.0.1:6379(TX)> incr email
QUEUED
127.0.0.1:6379(TX)> get age
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (integer) 5
3) OK
4) (error) ERR value is not an integer or out of range
5) "11"
注意:
運行時錯誤,即非語法錯誤,正確命令都會執行,錯誤命令返回錯誤。
二. redis集群
主從復制
概述
在現有企業中80%公司大部分使用的是Redis單機服務,在實際的場景當中單一節點的Redis容易面臨風險。
面臨問題:
- 機器故障。我們部署到一臺 Redis 服務器,當發生機器故障時,需要遷移到另外一臺服務器并且要保證數據是同步的。
- 容量瓶頸。當我們有需求需要擴容 Redis 內存時,從 16G 的內存升到 64G,單機肯定是滿足不了。當然,你可以重新買個 128G 的新機器。
解決辦法
要實現分布式數據庫的更大的存儲容量和承受高并發訪問量,我們會將原來集中式數據庫的數據分別存儲到其他多個網絡節點上。
注意:
Redis 為了解決這個單一節點的問題,也會把數據復制多個副本部署到其他節點上進行復制,實現 Redis的高可用,實現對數據的冗余備份從而保證數據和服務的高可用。
什么是主從復制
主從復制,是指將一臺Redis服務器的數據,復制到其他的Redis服務器。前者稱為主節點(master),后者稱為從節點(slave),數據的復制是單向的,只能由主節點到從節點。
主從復制的作用
- 數據冗余:主從復制實現了數據的熱備份,是持久化之外的一種數據冗余方式。
- 故障恢復:當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗余。
- 負載均衡:在主從復制的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(即寫Redis數據時應用連接主節點,讀Redis數據時應用連接從節點),分擔服務器負載;尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高Redis服務器的并發量。
- 高可用基石:除了上述作用以外,主從復制還是哨兵和集群能夠實施的基礎,因此說主從復制是Redis高可用的基礎。
主從復制環境搭建
編寫配置文件
新建redis6379.conf
include /usr/local/redis-7.2.4/redis.config
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb
新建redis6380.conf
include /usr/local/redis-7.2.4/redis.config
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
新建redis6381.conf
include /usr/local/redis-7.2.4/redis.config
pidfile /var/run/redis_6381.pid
port 6381
dbfilename dump6381.rdb
啟動三臺redis服務器
./redis-server ../redis6379.conf
./redis-server ../redis6380.conf
./redis-server ../redis6381.conf
查看系統進程
[root@localhost src]# ps -ef |grep redis
root 40737 1 0 22:05 ? 00:00:00 ./redis-server *:6379
root 40743 1 0 22:05 ? 00:00:00 ./redis-server *:6380
root 40750 1 0 22:05 ? 00:00:00 ./redis-server *:6381
root 40758 40631 0 22:05 pts/0 00:00:00 grep --color=auto redis
查看三臺主機運行情況
#打印主從復制的相關信息
./redis-cli -p 6379
./redis-cli -p 6380
./redis-cli -p 6381
127.0.0.1:6379> info replication
127.0.0.1:6380> info replication
127.0.0.1:6381> info replication
配從庫不配主庫
語法格式:
slaveof <ip> <port>
示例:
在6380和6381上執行。
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
OK
在主機上寫,在從機上可以讀取數據
set k1 v1
主從復制原理剖析
主從復制可以分為3個階段
- 連接建立階段(即準備階段)
- 數據同步階段
- 命令傳播階段
復制過程大致分為6個過程
- 保存主節點(master)信息。
執行 slaveof 后 查看狀態信息
info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
- 從節點(slave)內部通過每秒運行的定時任務維護復制相關邏輯,當定時任務發現存在新的主節點后,會嘗試與該節點建立網絡連接
- 從節點與主節點建立網絡連接
從節點會建立一個 socket 套接字,從節點建立了一個端口為51234的套接字,專門用于接受主節點發送的復制命令。
4、發送ping命令
連接建立成功后從節點發送 ping 請求進行首次通信。
作用:
- 檢測主從之間網絡套接字是否可用。
- 檢測主節點當前是否可以接受命令
-
權限驗證。
如果主節點設置了 requirepass 參數,則需要密碼驗證,從節點必須配置 masterauth 參數保證與主節點相同的密碼才能通過驗證;如果驗證失敗復制將終止,從節點重新發起復制流程。 -
同步數據集。
主從復制連接正常通信后,對于首次建立復制的場景,主節點會把持有的數據全部發送給從節點,這部分操作是耗時最長的步驟。
主從同步策略
主從剛剛連接的時候,進行全量同步;全同步結束后,進行增量同步。當然,如果有需要,slave 在任何時候都可以發起全量同步。redis 策略是,無論如何,首先會嘗試進行增量同步,如不成功,要求從機進行全量同步。
例如
保存一個緩存
set name jjy
記錄命令為
$3 \r \n
set \r \n
$4 \r \n
name \r \n
$5 \r \n
jjy \r \n
偏移量 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 |
---|---|---|---|---|---|---|---|---|---|
字節值 | $ | 3 | \r | \n | $ | 4 | n | a | m |
7.命令持續復制。
當主節點把當前的數據同步給從節點后,便完成了復制的建立流程。接下來主節點會持續地把寫命令發送給從節點,保證主從數據一致性。
哨兵監控
Redis主從復制缺點
當主機 Master 宕機以后,我們需要人工解決切換。
暴漏問題:
一旦主節點宕機,寫服務無法使用,就需要手動去切換,重新選取主節點,手動設置主從關系。
主從切換技術
當主服務器宕機后,需要手動把一臺從服務器切換為主服務器,這就需要人工干預,費事費力,還會造成一段時間內服務不可用。這不是一種推薦的方式,更多時候,我們優先考慮哨兵模式。
哨兵概述
哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的進程,作為進程,它會獨立運行。其原理是哨兵通過發送命令,等待Redis服務器響應,從而監控運行的多個Redis實例。
哨兵作用
- 集群監控:負責監控redis master和slave進程是否正常工作
- 消息通知:如果某個redis實例有故障,那么哨兵負責發送消息作為報警通知給管理員
- 故障轉移:如果master node掛掉了,會自動轉移到slave node上
- 配置中心:如果故障轉移發生了,通知client客戶端新的master地址
哨兵監控環境搭建
新建sentinel-26379.conf文件
#端口
port 26379
#守護進程運行
daemonize yes
#日志文件
logfile "26379.log"
sentinel monitor mymaster localhost 6379 2
參數:
sentinel monitor mymaster 192.168.92.128 6379 2 配置的含義是:該哨兵節點監控192.168.92.128:6379這個主節點,該主節點的名稱是mymaster,最后的2的含義與主節點的故障判定有關:至少需要2個哨兵節點同意,才能判定主節點故障并進行故障轉移。
新建sentinel-26380.conf文件
#端口
port 26380
#守護進程運行
daemonize yes
#日志文件
logfile "26380.log"
sentinel monitor mymaster localhost 6379 2
新建sentinel-26381.conf文件
#端口
port 26381
#守護進程運行
daemonize yes
#日志文件
logfile "26381.log"
sentinel monitor mymaster localhost 6379 2
哨兵節點的啟動
redis-sentinel sentinel-26379.conf
查看哨兵節點狀態
[root@localhost src]# ./redis-cli -p 26379
127.0.0.1:26379>
127.0.0.1:26379>
127.0.0.1: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=192.168.66.100:6379,slaves=2,sentinels=3
哨兵工作原理剖析
監控階段
注意:
- sentinel(哨兵1)----->向master(主)和slave(從)發起info,拿到全信息。
- sentinel(哨兵2)----->向master(主)發起info,就知道已經存在的sentinel(哨兵1)的信息,并且連接slave(從)。
- sentinel(哨兵2)----->向sentinel(哨兵1)發起subscribe(訂閱)。
通知階段
sentinel不斷的向master和slave發起通知,收集信息。
故障轉移階段
通知階段sentinel發送的通知沒得到master的回應,就會把master標記為SRI_S_DOWN,并且把master的狀態發給各個sentinel,其他sentinel聽到master掛了,說我不信,我也去看看,并把結果共享給各個sentinel,當有一半的sentinel都認為master掛了的時候,就會把master標記為SRI_0_DOWN。
問題來了:
這時就要把master給換掉了,到底誰當Master呢。
投票方式
方式:
自己最先接到哪個sentinel的競選通知就會把票投給它。
剔除一些情況:
- 不在線的
- 響應慢的
- 與原來master斷開時間久的
- 優先級原則
故障轉移
概述
演示當主節點發生故障時,哨兵的監控和自動故障轉移功能。
演示故障轉移
使用kill命令殺掉主節點
ps aux |grep redis
kill -9 pid
查看哨兵節點信息
如果此時立即在哨兵節點中使用info Sentinel命令查看。
[root@localhost src]# ./redis-cli -p 26379
127.0.0.1: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=127.0.0.1:6381,slaves=5,sentinels=3
注意:
會發現主節點還沒有切換過來,因為哨兵發現主節點故障并轉移,需要一段時間。
重啟6379節點
[root@localhost src]# ./redis-cli info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381
master_link_status:down
配置文件都會被改寫
故障轉移階段,哨兵和主從節點的配置文件都會被改寫
include /usr/local/redis/redis.conf
pidfile "/var/run/redis_6379.pid"
port 6379
dbfilename "dump6379.rdb"
# Generated by CONFIG REWRITE
daemonize yes
protected-mode no
appendonly yes
slowlog-max-len 1200
slowlog-log-slower-than 1000
save 5 1
user default on nopass ~* &* +@all
dir "/usr/local/redis"
replicaof 127.0.0.1 6381
結論
- 哨兵系統中的主從節點,與普通的主從節點并沒有什么區別,故障發現和轉移是由哨兵來控制和完成的。
- 哨兵節點本質上是redis節點。
- 每個哨兵節點,只需要配置監控主節點,便可以自動發現其他的哨兵節點和從節點。
- 在哨兵節點啟動和故障轉移階段,各個節點的配置文件會被重寫(config rewrite)。
Cluster模式
Redis有三種集群模式
- 主從模式
- Sentinel模式
- Cluster模式
哨兵模式的缺點
缺點:
- 當master掛掉的時候,sentinel 會選舉出來一個 master,選舉的時候是沒有辦法去訪問Redis的,會存在訪問瞬斷的情況;
- 哨兵模式,對外只有master節點可以寫,slave節點只能用于讀。盡管Redis單節點最多支持10W的QPS,但是在電商大促的時候,寫數據的壓力全部在master上。
- Redis的單節點內存不能設置過大,若數據過大在主從同步將會很慢;在節點啟動的時候,時間特別長;
Cluster模式概述
Redis集群是一個由多個主從節點群組成的分布式服務集群,它具有復制、高可用和分片特性。
Redis集群的優點
- Redis集群有多個master,可以減小訪問瞬斷問題的影響
- Redis集群有多個master,可以提供更高的并發量
- Redis集群可以分片存儲,這樣就可以存儲更多的數據
Cluster模式搭建
Redis的集群搭建最少需要3個master節點,我們這里搭建3個master,每個下面掛一個slave節點,總共6個Redis節點;
集群搭建
創建6個不同的redis節點,端口號分別為6379、6380、6381、6382、6383、6384。
注意:拷貝前必須刪除dump.rdb和appendonly.aof文件
1、新建配置文件
創建redis6379.config,redis6380.config,redis6381.config,redis6382.config,redis6383.config,redis6384.config文件修改配置文件中端口號使其和文件端口號對應。
daemonize yes
dir /usr/local/redis-7.2.4/redis-cluster/6382/
bind 192.168.47.100
port 6382
dbfilename dump6382.rdb
cluster-enabled yes
cluster-config-file nodes-6382.conf
cluster-node-timeout 5000
appendonly yes
protected-mode no
參數:
- cluster-config-file : 集群持久化配置文件,內容包含其它節點的狀態,持久化變量等,會自動生成在上面配置的dir目錄下。每個節點在運行過程中,會維護一份集群配置文件;每當集群信息發生變化時(如增減節點),集群內所有節點會將最新信息更新到該配置文件;當節點重啟后,會重新讀取該配置文件,獲取集群信息,可以方便的重新加入到集群中。集群配置文件由Redis維護,不需要人工修改。
- clouster-enabled: 開啟集群
創建文件夾
mkdir -p /usr/local/redis-7.2.4/redis-cluster/6379/
mkdir -p /usr/local/redis-7.2.4/redis-cluster/6380/
mkdir -p /usr/local/redis-7.2.4/redis-cluster/6381/
mkdir -p /usr/local/redis-7.2.4/redis-cluster/6382/
mkdir -p /usr/local/redis-7.2.4/redis-cluster/6383/
mkdir -p /usr/local/redis-7.2.4/redis-cluster/6384/
啟動六個節點
[root@bogon src]# ./redis-server ../redis6379.config
[root@bogon src]# ./redis-server ../redis6380.config
[root@bogon src]# ./redis-server ../redis6381.config
[root@bogon src]# ./redis-server ../redis6382.config
[root@bogon src]# ./redis-server ../redis6383.config
[root@bogon src]# ./redis-server ../redis6384.config
查看各個節點是否啟動成功
[root@bogon src]# ps -ef | grep redis
root 3889 1 0 09:56 ? 00:00:03 ./redis-server 0.0.0.0:6379 [cluster]
root 3895 1 0 09:56 ? 00:00:03 ./redis-server 0.0.0.0:6380 [cluster]
root 3901 1 0 09:57 ? 00:00:03 ./redis-server 0.0.0.0:6381 [cluster]
root 3907 1 0 09:57 ? 00:00:02 ./redis-server *:6382 [cluster]
root 3913 1 0 09:57 ? 00:00:02 ./redis-server 0.0.0.0:6383 [cluster]
root 3919 1 0 09:57 ? 00:00:02 ./redis-server 0.0.0.0:6384 [cluster]
root 4247 2418 0 10:22 pts/0 00:00:00 grep --color=auto redis
配置集群
命令格式: --cluster-replicas 1 表示為每個master創建一個slave節點
注意:這里的IP為每個節點所在機器的真實IP
[root@localhost src]# ./redis-cli --cluster create 192.168.47.100:6379 192.168.47.100:6380 192.168.47.100:6381 192.168.47.100:6382 192.168.47.100:6383 192.168.47.100:6384 --cluster-replicas 1
驗證集群
連接任意一個客戶端
./redis-cli -h 192.168.47.100 -p 6379 -c
參數:
‐h : host地址
-p : 端口號
‐c : 表示集群模式
數據寫測試
[root@bogon src]# ./redis-cli -p 6379 -c
127.0.0.1:6379> set name zhangsan
-> Redirected to slot [5798] located at 192.168.47.100:6380
OK
192.168.47.100:6380> get name
"zhangsan"
192.168.47.100:6380>
[root@bogon src]# ./redis-cli -p 6383 -c
127.0.0.1:6383> get name
-> Redirected to slot [5798] located at 192.168.47.100:6380
"zhangsan"
192.168.47.100:6380>
[root@bogon src]# ./redis-cli -p 6383 -c
127.0.0.1:6383> readonly
OK
127.0.0.1:6383> get name
"zhangsan"
127.0.0.1:6383>
Cluster模式原理剖析
Redis Cluster將所有數據劃分為16384個slots(槽位),每個節點負責其中一部分槽位。槽位的信息存儲于每個節點中。只有master節點會被分配槽位,slave節點不會分配槽位。
槽位定位算法: k1 = 127001
Cluster 默認會對 key 值使用 crc16 算法進行 hash 得到一個整數值,然后用這個整數值對 16384 進行取模來得到具體槽位。
HASH_SLOT = CRC16(key) % 16384
故障恢復
查看節點
192.168.66.103:8001> cluster nodes
殺死Master節點
lsof -i:8001
kill -9 pid
觀察節點信息
Java操作Redis集群
修改配置文件
spring.data.redis.cluster.nodes=192.168.47.100:6381,192.168.47.100:6383,192.168.47.100:6380
注意
1、Redis集群需要至少3個節點才能保證高可用性。
2、應該盡量避免在Redis集群的運行過程中添加或刪除節點,因為這可能導致數據遷移,進而影響Redis集群的整體性能。
Java編寫的代碼
@SpringBootTest
public class CluseterTest {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Testvoid string() {// 保存字符串redisTemplate.opsForValue().set("itbaizhan","itbaizhan123");System.out.println(redisTemplate.opsForValue().get("itbaizhan"));}
}
如果我的內容對你有幫助,請點贊,評論,收藏。創作不易,大家的支持就是我堅持下去的動力