Redis04

redis

一、redis的作用和使用場景

redis是一個內存級的高速緩存數據庫。(對比磁盤IO)

使用場景:1、并發訪問量大的 2、數據量小 3、修改不頻繁

項目中:1、驗證碼 2、登錄成功用戶信息 3、首頁(模塊數據 輪播圖,商品分類,熱點模塊,推薦模塊) 4、購物車(商品信息)

二、redis支持的數據類型有哪些?

目前支持10種,常用的有5種:String、list、set、zset、hash(map)、stream

三、redis的常用命令

通用命令

每種數據類型各自的命令

string類型

 設置過期時間1、set k1 v1 ex 1002、setex k1 100 v23、set k1 v1 expire k1 100

list類型 (有序,可以重復)

1.94.230.82:6381> lpush addressList hangzhou zhengzhou guangzhou
(integer) 3
1.94.230.82:6381> llen addressList
(integer) 3
1.94.230.82:6381> lrange addressList 0 -1
1) "guangzhou"
2) "zhengzhou"
3) "hangzhou"

set類型(無序、不可重復)

1.94.230.82:6381> sadd subjects java c java
(integer) 2
1.94.230.82:6381> sadd subjects c
(integer) 0
1.94.230.82:6381> sadd subjects mysql
(integer) 1
1.94.230.82:6381> smembers subjects
1) "mysql"
2) "java"
3) "c"
1.94.230.82:6381> sadd subjects py
(integer) 1
1.94.230.82:6381> smembers subjects
1) "mysql"
2) "java"
3) "py"
4) "c"

hash類型(map類型 : 存儲map名 key value 存儲對象:對象名 屬性名 屬性值)

1.94.230.82:6381> hset user id 111
(integer) 1
1.94.230.82:6381> hset user name zhangsan
(integer) 1
1.94.230.82:6381> hset user age 20
(integer) 1
1.94.230.82:6381> hset user age 22
(integer) 0
1.94.230.82:6381> hget user id
"111"
1.94.230.82:6381> hget user name
"zhangsan"
1.94.230.82:6381> hget user age
"22"
1.94.230.82:6381> hdel user name
(integer) 1
1.94.230.82:6381> hkeys user
1) "id"
2) "age"
1.94.230.82:6381> hvals user
1) "111"
2) "22"

zset 有序的set集合 有序,不能重復 (給每一個value值,添加一個數值,通過數值保持有序)

1.94.230.82:6381> zadd sbs 1  java  2  c  3 py
(integer) 3
1.94.230.82:6381> zrange sbs 0 -1
1) "java"
2) "c"
3) "py"
1.94.230.82:6381> zadd sbs 10 html
(integer) 1
1.94.230.82:6381> zrange sbs 0 -1
1) "java"
2) "c"
3) "py"
4) "html"
1.94.230.82:6381> zadd sbs 5 c#
(integer) 1
1.94.230.82:6381> zrange sbs 0 -1
1) "java"
2) "c"
3) "py"
4) "c#"
5) "html"

四、redis的持久化機制

rdb:默認 快照模式

定時同步(1min 10000、5min 10、15min 1)

可能造成最后一次同步之后的數據丟失

性能高(新建一個進程 執行數據同步操作,不影響主進程)

dump.rdb 本地磁盤文件(實時數據)

恢復速度快

aof:日志追加模式 日志文件大

rdb文件 全量

追加命令 到 aof日志文件

恢復慢 rdb+aof 逐個命令執行,恢復

更安全,丟失的數據更少

同步機制(no(30s) always everySec)

五、數據的刪除策略

定時刪除 定時器刪除(根據設置的過期時間)

定期刪除 根據配置文件參數hz值,60/hz 循環檢測各個倉庫刪除(抽取w個值進行檢測,根據過期key的百分比 25% 循環刪除)

惰性刪除 過期后不立即刪除。(使用時判斷,過期刪除)

六、數據的淘汰策略

volatile- lru lfu ttl random

allkeys- lru lfu random

no 放棄驅逐

七、事務機制

multi exec discard watch unwatch

事務的特點:

是否滿足原子性: 不滿足

八、鎖機制

樂觀鎖: watch unwatch

悲觀鎖:setnx 分布式鎖 setnx(key,value) 1 執行代碼 ---- del key

九、發布訂閱機制

publish 頻道 message

subscribe 頻道

十、一主二從(高可用)

實現讀寫分離、主從復制、主機執行讀寫,從機執行讀取。

主從切換

手動切換: slaveof no one slaveof ip port
自動切換: 哨兵模式

哨兵

哨兵的作用是監控 redis系統的運行狀況,他的功能如下:

監控主從數據庫是否正常運行

master出現故障時,自動將slave轉化為master

多哨兵配置的時候,哨兵之間也會自動監控

多個哨兵可以監控同一個redis

哨兵工作機制

./redis-sentinel sentinel.conf

哨兵進程啟動時會讀取配置文件的內容,通過sentinel monitor master-name ip port quorum查找到master的ip端口。一個哨兵可以監控多個master數據庫,只需要提供多個該配置項即可。

配置文件還定義了與監控相關的參數,比如master多長時間無響應即即判定位為下線。

哨兵啟動后,會與要監控的master建立倆條連接:

一條連接用來訂閱master的sentinel:hello頻道與獲取其他監控該master的哨兵節點信息

另一條連接定期向master發送INFO等命令獲取master本身的信息

與master建立連接后,哨兵會執行三個操作,這三個操作的發送頻率都可以在配置文件中配置:

定期向master和slave發送INFO命令

定期向master和slave的sentinel:hello頻道發送自己的信息

定期向master、slave和其他哨兵發送PING命令

這三個操作的意義非常重大,發送INFO命令可以獲取當前數據庫的相關信息從而實現新節點的自動發現。所以說哨兵只需要配置master數據庫信息就可以自動發現其slave信息。獲取到slave信息后,哨兵也會與slave建立倆條連接執行監控。通過INFO命令,哨兵可以獲取主從數據庫的最新信息,并進行相應的操作,比如角色變更等。

接下來哨兵向主從數據庫的sentinel:hello頻道發送信息與同樣監控這些數據庫的哨兵共享自己的信息,發送內容為哨兵的ip端口、運行id、配置版本、master名字、master的ip端口還有master的配置版本。這些信息有以下用處:

其他哨兵可以通過該信息判斷發送者是否是新發現的哨兵,如果是的話會創建一個到該哨兵的連接用于發送PING命令。

其他哨兵通過該信息可以判斷master的版本,如果該版本高于直接記錄的版本,將會更新

當實現了自動發現slave和其他哨兵節點后,哨兵就可以通過定期發送PING命令定時監控這些數據庫和節點有沒有停止服務。發送頻率可以配置,但是最長間隔時間為1s,可以通過sentinel down-after-milliseconds mymaster 600設置。

如果被ping的數據庫或者節點超時未回復,哨兵認為其主觀下線。如果下線的是master,哨兵會向其他哨兵點發送命令詢問他們是否也認為該master主觀下線,如果達到一定數目(即配置文件中的quorum)投票,哨兵會認為該master已經客觀下線,并選舉領頭的哨兵節點對主從系統發起故障恢復。

如上文所說,哨兵認為master客觀下線后,故障恢復的操作需要由選舉的領頭哨兵執行,選舉采用Raft算法:

發現master下線的哨兵節點(我們稱他為A)向每個哨兵發送命令,要求對方選自己為領頭哨兵

如果目標哨兵節點沒有選過其他人,則會同意選舉A為領頭哨兵

如果有超過一半的哨兵同意選舉A為領頭,則A當選

如果有多個哨兵節點同時參選領頭,此時有可能存在一輪投票無競選者勝出,此時每個參選的節點等待一個隨機時間后再次發起參選請求,進行下一輪投票精選,直至選舉出領頭哨兵

選出領頭哨兵后,領頭者開始對進行故障恢復,從出現故障的master的從數據庫中挑選一個來當選新的master,選擇規則如下:

所有在線的slave中選擇優先級最高的,優先級可以通過slave-priority配置

如果有多個最高優先級的slave,則選取復制偏移量最大(即復制越完整)的當選

如果以上條件都一樣,選取id最小的slave

挑選出需要繼任的slave后,領頭哨兵向該數據庫發送命令使其升格為master,然后再向其他slave發送命令接受新的master,最后更新數據。將已經停止的舊的master更新為新的master的從數據庫,使其恢復服務后以slave的身份繼續運行。

十一、集群模式(高可用)

3主6從

創建redis目錄和配置文件 由于這里需要配置6個redis實例的配置文件,所以在這里,可以先創建一個模板配置文件,之后使用代碼批量替換的方式來創建每個redis的配置文件。

創建模板文件

創建目錄

mkdir -p /data/docker_redis/
?
編寫redis_cluster.conf.template文件
?
vi redis_cluster.conf.template
port ${PORT}
requirepass 1234
masterauth 1234
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 82.157.9.251
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
 

在這里需要講解2個參數 cluster-announce-port:此端口為redis提供服務端口,用于應用客戶端連接 cluster-announce-bus-port:此端口用于redis集群進行故障檢測、配置更新、故障轉移授權和內部通訊使用,不用于應用客戶端連接使用。

創建6個redis實例的數據目錄,配置文件目錄和配置文件

for port in `seq 8001 8006`; do \mkdir -p /data/redis_data/${port}/conf \&& PORT=${port} envsubst < /data/docker_redis/redis_cluster.conf.template > /data/redis_data/${port}/conf/redis.conf \&& mkdir -p /data/redis_data/${port}/data;\
done

批量創建容器 在這里使用for循環批量創建redis容器,代碼如下所示

for port in $(seq 8001 8006); do \docker run -id -p ${port}:${port} -p 1${port}:1${port} --restart always --name redis-${port} \-v /data/redis_data/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \-v /data/redis_data/${port}/data:/data \redis:7.0.2 redis-server /usr/local/etc/redis/redis.conf; \
done
?
開放防火墻端口:(云服務器端口也要開放)
sudo firewall-cmd --permanent --add-port=8001-8006/tcp
sudo firewall-cmd --permanent --add-port=18001-18006/tcp
?
啟動容器:
for port in $(seq 8001 8006); do \docker start redis-${port} ;\
done

在這里使用-v參數,讓容器的redis配置參數和數據全部使用宿主機的文件目錄。這樣做的好處是,保證redis的數據不丟失。

查看剛剛創建的redis容器

[root@mysql data]# docker ps
CONTAINER ID ? ? ?  IMAGE ? ? ? ? ? ? ?  COMMAND ? ? ? ? ? ? ? ?  CREATED ? ? ? ? ? ? STATUS ? ? ? ? ? ?  PORTS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  NAMES
f4c971ce2d84 ? ? ?  redis:7.0.2-buster ? "docker-entrypoint.s鈥 6 seconds ago ? ? ? Up 5 seconds ? ? ?  0.0.0.0:8006->8006/tcp, 6379/tcp, 0.0.0.0:18006->18006/tcp ? redis-8006
1b5a8b0a1c93 ? ? ?  redis:7.0.2-buster ? "docker-entrypoint.s鈥 7 seconds ago ? ? ? Up 6 seconds ? ? ?  0.0.0.0:8005->8005/tcp, 6379/tcp, 0.0.0.0:18005->18005/tcp ? redis-8005
35d8fe01fc71 ? ? ?  redis:7.0.2-buster ? "docker-entrypoint.s鈥 7 seconds ago ? ? ? Up 6 seconds ? ? ?  0.0.0.0:8004->8004/tcp, 6379/tcp, 0.0.0.0:18004->18004/tcp ? redis-8004
408e5302378a ? ? ?  redis:7.0.2-buster ? "docker-entrypoint.s鈥 8 seconds ago ? ? ? Up 7 seconds ? ? ?  0.0.0.0:8003->8003/tcp, 6379/tcp, 0.0.0.0:18003->18003/tcp ? redis-8003
c1c23c543233 ? ? ?  redis:7.0.2-buster ? "docker-entrypoint.s鈥 8 seconds ago ? ? ? Up 7 seconds ? ? ?  0.0.0.0:8002->8002/tcp, 6379/tcp, 0.0.0.0:18002->18002/tcp ? redis-8002
c752fab6c6b8 ? ? ?  redis:7.0.2-buster ? "docker-entrypoint.s鈥 9 seconds ago ? ? ? Up 8 seconds ? ? ?  0.0.0.0:8001->8001/tcp, 6379/tcp, 0.0.0.0:18001->18001/tcp ? redis-8001

創建redis-cluster集群 6個redis容器創建好之后,選擇其中的一個容器進入,進行redis-cluster集群創建

[root@mysql bin]# docker exec -it redis-8001 /bin/bash
root@f4c971ce2d84:~# redis-cli -a 1234 --cluster create 82.157.9.251:8001 82.157.9.251:8002 82.157.9.251:8003 82.157.9.251:8004 82.157.9.251:8005 82.157.9.251:8006 --cluster-replicas 1
回車后顯示:
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 82.157.9.251:8005 to 82.157.9.251:8001
Adding replica 82.157.9.251:8006 to 82.157.9.251:8002
Adding replica 82.157.9.251:8004 to 82.157.9.251:8003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001slots:[0-5460] (5461 slots) master
M: 0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002slots:[5461-10922] (5462 slots) master
M: d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003slots:[10923-16383] (5461 slots) master
S: 96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004replicates c9e549f4d04d4466d2550d1e027412304099b1f2
S: 8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005replicates 0956927ee74737d5ff91a1885e77f94d531dab76
S: aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006replicates d6321788b2717b4142390c158ba70ca758f70964
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 82.157.9.251:8001)
M: c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001slots:[0-5460] (5461 slots) master1 additional replica(s)
M: 0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002slots:[5461-10922] (5462 slots) master1 additional replica(s)
S: 96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004slots: (0 slots) slavereplicates c9e549f4d04d4466d2550d1e027412304099b1f2
S: aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006slots: (0 slots) slavereplicates d6321788b2717b4142390c158ba70ca758f70964
S: 8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005slots: (0 slots) slavereplicates 0956927ee74737d5ff91a1885e77f94d531dab76
M: d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003slots:[10923-16383] (5461 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
 

上述命令執行之后,redis-cluster集群就搭建好了

在主機上測試:

模仿某一節點故障:

在cmd窗口:

重啟:docker start redis-8001

下面是整個redis-cluster集群的架構圖

redis-cluster集群狀態檢查 檢查redis-cluster集群狀態

root@f4c971ce2d84:~# redis-cli -a 1234 --cluster check 1.94.230.82:8001
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
82.157.9.251:8001 (c9e549f4...) -> 0 keys | 5461 slots | 1 slaves.
82.157.9.251:8002 (0956927e...) -> 0 keys | 5462 slots | 1 slaves.
82.157.9.251:8003 (d6321788...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 82.157.9.251:8001)
M: c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001slots:[0-5460] (5461 slots) master1 additional replica(s)
M: 0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002slots:[5461-10922] (5462 slots) master1 additional replica(s)
S: 96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004slots: (0 slots) slavereplicates c9e549f4d04d4466d2550d1e027412304099b1f2
S: aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006slots: (0 slots) slavereplicates d6321788b2717b4142390c158ba70ca758f70964
S: 8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005slots: (0 slots) slavereplicates 0956927ee74737d5ff91a1885e77f94d531dab76
M: d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003slots:[10923-16383] (5461 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
 

檢查redis集群節點信息

root@f4c971ce2d84:~# redis-cli -c -a 1234 -h 82.157.9.251 -p 8001
82.157.9.251:8001> cluster nodes
0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002@18002 master - 0 1603265855374 2 connected 5461-10922
96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004@18004 slave c9e549f4d04d4466d2550d1e027412304099b1f2 0 1603265856080 4 connected
aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006@18006 slave d6321788b2717b4142390c158ba70ca758f70964 0 1603265855575 6 connected
8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005@18005 slave 0956927ee74737d5ff91a1885e77f94d531dab76 0 1603265855575 5 connected
d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003@18003 master - 0 1603265856382 3 connected 10923-16383
c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001@18001 myself,master - 0 1603265855000 1 connected 0-5460
?

在這里可以很清晰明了的看到有3個master節點和3個slave節點的IP地址和端口信息。

redis-cluster連接測試

redis-cluster搭建好之后,隨意連接一個redis節點,無論是主節點還是從節點都可以,在這里選擇連接一個從節點。

82.157.9.251:8001> cluster nodes
0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002@18002 master - 0 1603265855374 2 connected 5461-10922
96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004@18004 slave c9e549f4d04d4466d2550d1e027412304099b1f2 0 1603265856080 4 connected
aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006@18006 slave d6321788b2717b4142390c158ba70ca758f70964 0 1603265855575 6 connected
8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005@18005 slave 0956927ee74737d5ff91a1885e77f94d531dab76 0 1603265855575 5 connected
d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003@18003 master - 0 1603265856382 3 connected 10923-16383
c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001@18001 myself,master - 0 1603265855000 1 connected 0-5460
?
?
root@f4c971ce2d84:~# redis-cli -c -a 1234 -h 82.157.9.251 -p 8004
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
82.157.9.251:8004> 
82.157.9.251:8004> set 5 test5
-> Redirected to slot [9974] located at 82.157.9.251:8002
82.157.9.251:8002> 
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.

當在slave節點寫入數據時,redis-cluster將你的寫請求重定向到另一個master節點了.

root@f4c971ce2d84:~# redis-cli -c -a 1234 -h 82.157.9.251 -p 8006
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
82.157.9.251:8006> 
82.157.9.251:8006> get 5
-> Redirected to slot [9974] located at 82.157.9.251:8002
"test5"
82.157.9.251:8002>

十二、重點題

redis和java結合

redis雪崩、穿透、擊穿

1. redis緩存使用流程

使用Redis緩存數據的流程是:

  1. 數據查詢首先進行緩存查詢。

  2. 如果數據存在則直接返回緩存數據。

  3. 如果數據不存在,就對數據庫進行查詢,并把查詢到的數據放進緩存。

  4. 如果數據庫查詢數據為空,則不放進緩存。

2. 緩存穿透

2.1. 概念

緩存穿透是指查詢緩存和數據庫中都不存在的數據。比如id為-1的數據。

2.2. 解決方案
  • 緩存空值:當第一次請求時,數據不存在 Redis 也不存在數據庫的時候,設置一個缺省值(比如:None)。當后續再次進行查詢則直接返回空值或者缺省值。

    //偽代碼
    public object GetProductListNew(String key) {//首先查詢redis數據String value = redis.get(key);//如果redis中沒有數據if(value == null){//查詢數據庫中的數據String dbValue = db.get();//如果數據庫中的數據為null,則設置默認值if (dbValue == null) {dbValue = "none";}//將數據存儲到redisredis.set(key,dbValue,50000);//返回return dbvalue;}}else{//第二次查詢數據時,redis有數據,就直接返回return value;}
    }
  • 布隆過濾器:在數據寫入數據庫的同時將這個 ID 同步到到布隆過濾器中,當請求的 id 不存在布隆過濾器中則說明該請求查詢的數據一定沒有在數據庫中保存,就不要去數據庫查詢了。

    <dependencies> ?<dependency> ?<groupId>com.google.guava</groupId> ?<artifactId>guava</artifactId> ?<version>23.0</version> ?</dependency> ?
    </dependencies> 
    //偽代碼
    public class BloomFilterTest {private static final int capacity = 1000000;private static final int key = 999998;private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), capacity);static {for (int i = 0; i < capacity; i++) {bloomFilter.put(i);}}
    ?public static void main(String[] args) {/*返回計算機最精確的時間,單位微妙*/long start = System.nanoTime();if (bloomFilter.mightContain(key)) {System.out.println("成功過濾到" + key);}long end = System.nanoTime();System.out.println("布隆過濾器消耗時間:" + (end - start));int sum = 0;for (int i = capacity + 20000; i < capacity + 30000; i++) {if (bloomFilter.mightContain(i)) {sum = sum + 1;}}System.out.println("錯判率為:" + sum);}
    }

3. 緩存雪崩

3.1. 概念

是指在某一個時間段,redis服務器故障或者redis緩存的數據集中全部過期失效或者大量key過期失效,在緩存集中失效的這個時間段對數據的訪問查詢,都落到了數據庫上,對于數據庫而言,就會產生周期性的壓力。

3.2. 解決方案

事前:

redis服務器設置高可用(一主二從或者集群3主3從)

  • 隨機設置key失效時間,避免大量key集體失效。

  • 不設置過期時間(不推薦)。

  • 用加鎖或者隊列的方式保證來保證不會有大量的線程對數據庫一次性進行讀寫。

  • 跑定時任務,在緩存失效前刷進新的緩存。

    事中:

    可以考略多種緩存機制,比如redis緩存+其他緩存機制 spring cache +mysql

    事后:

    redis崩潰、mysql崩潰,系統崩潰

    解決方案:快速恢復系統(重啟mysql、重啟redis服務 快速恢復數據到內存中 rdb aof機制 、重啟java服務)

4. 緩存擊穿

4.1. 概念

指一個Key非常熱點,在不停的扛著大并發,大并發集中對這一個點進行訪問,當這個Key在失效的瞬間,持續的大并發就穿破緩存,直接請求數據庫,就像在一個完好無損的桶上鑿開了一個洞。

4.2. 解決方案
  • 預先把熱門數據提前存入 Redis 中,并設熱門數據的過期時間超大值。

  • 使用分布式鎖,當發現緩存失效的時候,不是立即從數據庫加載數據。而是先獲取分布式鎖,獲取鎖成功才執行數據庫查詢和寫數據到緩存的操作,獲取鎖失敗,則說明當前有線程在執行數據庫查詢操作,當前線程睡眠一段時間在重試。這樣只讓一個請求去數據庫讀取數據。

    //偽代碼
    public String get(key) {String value = redis.get(key);if (value == null) { //代表緩存值過期//設置3min的超時,防止del操作失敗的時候,下次緩存過期一直不能load dbif (redis.setnx(key_mutex, 1, 3 * 60) == 1) { ?//代表設置成功value = db.get(key);redis.set(key, value, expire_secs);redis.del(key_mutex);} else { ?//這個時候代表同時候的其他線程已經load db并回設到緩存了,這時候重試獲取緩存值即可sleep(50);get(key); ?//重試}} else {return value; ? ? ?}}

十三、springboot項目和redis的整合

1、spring-boot-starter-data-redis

2、配置redis的連接信息(host、port、password、database)

3、使用redisTemplate模版工具類

4、常見方法

redisTemplate.opsForValue.set(key,value);

redisTemplate.opsForValue.get(key)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86018.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86018.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86018.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡學習筆記:TCP可靠傳輸實現、超時重傳時間選擇

文章目錄 一、TCP可靠傳輸實現二、TCP超時重傳時間選擇 一、TCP可靠傳輸實現 TCP可靠傳輸的實現&#xff0c;主要基于發送方和接收方的滑動窗口&#xff0c;以及確認機制&#xff1a; 發送方在未收到確認&#xff08;ACK&#xff09;前&#xff0c;可以將序號落在發送窗口內的…

Perl 正則表達式

Perl 正則表達式 引言 Perl 正則表達式&#xff08;Regular Expressions&#xff09;是Perl編程語言中一個強大且靈活的工具&#xff0c;用于字符串處理和模式匹配。正則表達式在文本處理、數據驗證、搜索和替換等任務中發揮著至關重要的作用。本文將深入探討Perl正則表達式的…

Security: RSA: 1024 bit 長度已經變得不安全了

文章目錄 參考推薦限制RHEL相關配置man crypto-policies包含的應用使用方法是配置文件include參考 https://csrc.nist.gov/pubs/sp/800/57/pt1/r2/final https://www.linuxquestions.org/questions/linux-security-4/1024-bit-dsa-vs-2048-bit-rsa-4175439131/ https://csrc.n…

第一課:大白話中的機器學習

各位看官好啊!今天咱們來聊一個聽起來高大上但實際上特別接地氣的玩意兒——機器學習。別被這名字嚇到,它其實就是教電腦像人類一樣學習知識的一套方法。想象一下你教你家狗子坐下、握手的過程,機器學習差不多就是這么回事,只不過"學生"換成了電腦。 一、啥是機…

實現 el-table 中鍵盤方向鍵導航功能vue2+vue3(類似 Excel)

實現 el-table 中鍵盤方向鍵導航功能vue2vue3&#xff08;類似 Excel&#xff09; 功能需求 在 Element UI 的 el-table 表格中實現以下功能&#xff1a; 使用鍵盤上下左右鍵在可編輯的 el-input/el-select 之間移動焦點焦點移動時自動定位到對應單元格支持光標位置自動調整…

MyBatis:從入門到進階

&#x1f4cc; 摘要 在 Java 后端開發中&#xff0c;MyBatis 是一個非常流行且靈活的持久層框架。它不像 Hibernate 那樣完全封裝 SQL&#xff0c;而是提供了對 SQL 的精細控制能力&#xff0c;同時又具備 ORM&#xff08;對象關系映射&#xff09;的功能。 本文將帶你從 MyB…

leetcode51.N皇后:回溯算法與沖突檢測的核心邏輯

一、題目深度解析與N皇后問題本質 題目描述 n皇后問題研究的是如何將n個皇后放置在nn的棋盤上&#xff0c;并且使皇后彼此之間不能相互攻擊。給定一個整數n&#xff0c;返回所有不同的n皇后問題的解決方案。每一種解法包含一個明確的n皇后問題的棋子放置方案&#xff0c;該方…

算法-每日一題(DAY9)楊輝三角

1.題目鏈接&#xff1a; 118. 楊輝三角 - 力扣&#xff08;LeetCode&#xff09; 2.題目描述&#xff1a; 給定一個非負整數 numRows&#xff0c;生成「楊輝三角」的前 numRows 行。 在「楊輝三角」中&#xff0c;每個數是它左上方和右上方的數的和。 示例 1: 輸入: numRo…

【MATLAB代碼】制導方法介紹與例程——追蹤法,適用于二維平面,目標是移動的|附完整源代碼

追蹤法(追蹤導引法)是一種常見的導彈導引方式,其基本原理是保持導彈的速度矢量始終指向目標。在追蹤法中,導彈的加速度可以表示為指向目標的加速度。 本文給出二維平面下,移動目標的追蹤法導引的介紹、公式與matlab例程 訂閱專欄后,可以直接查看完整源代碼 文章目錄 運行…

小白的進階之路系列之十八----人工智能從初步到精通pytorch綜合運用的講解第十一部分

從零開始的NLP:使用序列到序列網絡和注意力機制進行翻譯 我們將編寫自己的類和函數來預處理數據以完成我們的 NLP 建模任務。 在這個項目中,我們將訓練一個神經網絡將法語翻譯成英語。 [KEY: > input, = target, < output]> il est en train de peindre un table…

SSL安全證書:數字時代的網絡安全基石

SSL安全證書&#xff1a;數字時代的網絡安全基石 在當今數字化浪潮中&#xff0c;網絡通信安全已成為個人、企業和組織不可忽視的核心議題。SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接層&#xff09;安全證書作為保障數據傳輸安全的關鍵技術&#xff0c;通過加…

LLM-201: OpenHands與LLM交互鏈路分析

一、核心交互鏈路架構 #mermaid-svg-ZBqCSQk1PPDkIXNx {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-icon{fill:#552222;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-text{fill:#552222;strok…

【項目】仿muduo庫one thread one loop式并發服務器SERVER模塊(下)

&#x1f4da; 博主的專欄 &#x1f427; Linux | &#x1f5a5;? C | &#x1f4ca; 數據結構 | &#x1f4a1;C 算法 | &#x1f152; C 語言 | &#x1f310; 計算機網絡 |&#x1f5c3;? mysql 項目文章&#xff1a; 仿muduo庫one thread one loop式并發服務器…

數據庫索引結構 B 樹、B + 樹與哈希索引在不同數據查詢場景下的適用性分析

一、數據庫索引結構B樹 樹概述 樹是一種多路平衡查找樹&#xff0c;廣泛應用于數據庫和文件系統中。B樹的節點可以存儲多個數據元素&#xff0c;并且保持樹的平衡&#xff0c;以提高查詢效率。 適用性分析 在數據量較大&#xff0c;范圍查找較多的場景下&#xff0c;B樹的查詢效…

Linux進程間通信——信號

1.信號的介紹 信號( Signal )是 Unix, 類Unix以及其他POSIX兼容的操作系統中進程間通信的一種有限制的手段。 1&#xff09;信號是在軟件層面上對中斷機制的一種模擬&#xff0c;是一種異步通信方式。2&#xff09;信號可以直接進行用戶空間進程和內核進程之間的交互&#xff…

Bytemd@Bytemd/react詳解(編輯器實現基礎AST、插件、跨框架)

ByteMD Markdown編輯器詳細解釋&修改編輯器默認樣式&#xff08;高度300px) AST樹詳解 [ByteMD 插件系統詳解(https://blog.csdn.net/m0_55049655/article/details/148811248?spm1001.2014.3001.5501) Sevelet編寫的Bytemd如何適配到React中 ??1?? 背景概述 Byte…

《Redis》事務

文章目錄 Redis中的原子性Redis的事物和MySQL事務的區別Redis實現事務什么場景下&#xff0c;會使用事務? Redis事務相關命令watch命令的實現原理 總結 Redis中的原子性 Redis的原子性不同于MySQL的原子性。 Redis的事物和MySQL事務的區別 但是注意體會Redis的事務和MySQL…

Elasticsearch Kibana (一)

一、官方文檔 elasticsearch官網&#xff1a;elasticsearch官網 elasticsearch源碼&#xff1a;elasticsearch源碼 ik分詞器&#xff1a; ik分詞器 ik分詞器下載&#xff1a;ik分詞器下載 elasticsearch 版本選擇&#xff1a;elasticsearch 版本選擇 官方推薦Elasticsearch和j…

[linux] Ubuntu 24軟件下載和安裝匯總(自用)

經常重裝系統&#xff0c;備份下&#xff0c;有用的也可以參考。 安裝圖形界面 apt install ubuntu-desktop systemctl set-default graphical.target reboot 安裝chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo apt insta…

分布變化的模仿學習算法

與傳統監督學習不同,直接模仿學習在不同時刻所面臨的數據分布可能不同.試設計一個考慮不同時刻數據分布變化的模仿學習算法 import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset from…