Redis 互联网开发必看
一,搭建環境
Windows環境搭建
redis-server.exe --service-install redis.windows.conf [–loglevel verbose] – 服務部署
卸載服務:redis-server --service-uninstall
開啟服務:redis-server --service-start
停止服務:redis-server --service-stop
啟動客戶端:redis-cli.exe -h 127.0.0.1 -p 6379 -a requirepass
Redis桌面管理工具[下載地址:https://redisdesktop.com/download]
Redis如何設置密碼及驗證密碼
設置密碼:config set requirepass 123456
授權密碼:auth 123456
刪除密碼:config set requirepass “”
針對當前啟動的服務設置密碼,卸載之后,重新安裝還需要進行設置密碼
linux 環境搭建
官網
$ wget https://download.redis.io/releases/redis-6.2.1.tar.gz
提示wget命令沒有找到,執行:yum -y install wget
$ tar xzf redis-6.2.1.tar.gz
$ cd redis-6.2.1
$ make
make:linux中make是用來編譯的,它從Makefile中讀取指令,然后編譯
make:異常
錯誤信息: cc: command not found
解決方案:yum -y install gcc gcc-c++ libstdc+±devel
make:異常(fatal error:jemalloc/jemalloc.h:no such file or directory)
make MALLOC=libc(編譯時添加參數防止Linux下make報錯)
make test : 異常 you need tcl 8.5 or newer
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/
cd /usr/local/tcl8.6.1/unix/
./configure
make
make install
啟動服務端 【$ src/redis-server 】【不指定conf,使用默認的配置,正式使用時需要配置啟動的conf文件】
啟動客戶端【$ src/redis-cli】
創建redis文件夾并將源文件中的服務器和客戶端移入
$ mkdir -p /usr/local/redis
$ cp /usr/local/src/redis-5.0.4/src/redis-server /usr/local/redis/
$ cp /usr/local/src/redis-5.0.4/src/redis-cli /usr/local/redis/
設置Redis開機自啟動
$ cd /usr/local/src/redis-5.0.4/utils
$ ./install_server.sh
出現 This systems seems to use systemd 錯誤,
則 vi ./install_server.sh 注釋對應的代碼即可
conf 指定文件
log /var/log/redis_6379.log
data /var/lib/redis/6379
Copied /tmp/6379.conf => /etc/init.d/redis_6379【軟連接】
#查看redis進程
$ ps -ef | grep redis
#修改redis配置
$ whereis redis
$ vim /etc/redis/6379.conf
#找到并注釋掉 bind 127.0.0.1
#bind 127.0.0.1 #限制IP
daemonize yes # 以后臺守護進程方式運行
protected-mode no
requirepass 123456 # 設置密碼
#重啟redis服務器
$ service redis_6379 restart
在unils 文件夾下執行
#端口添加防火墻
$ firewall-cmd --zone=public --add-port=6379/tcp --permanent
#重啟防火墻
systemctl reload firewalld
systemctl start firewalld
systemctl stop firewalld
#建立redis客戶端命令的軟連接
$ ln -s /usr/local/redis/redis-cli /usr/bin/redis【軟連接】
$ redis
127.0.0.1:6379> AUTH 123456
#開啟關閉redis服務
$ service redis_6379 start
$ service redis_6379 restart
$ service redis_6379 stop
查看redis 服務端版本
redis-server -v
鏈接客戶端,執行 info 命令
二,CAP
C:Consistency
一致性:指的是強一致性,也就是數據更新完,訪問任何節點的數據完全一致,要和弱一致性,最終一致性區分開來
A:Availability
可用性:指高可用還包括不能出現延遲,比如節點B等待數據同步而阻塞請求,任何沒有發生故障的服務必須在有限的時間內返回合理的結果集
P:Partiton tolerence
分區容忍性:指網絡意義上的分區。由于網絡是不可靠的,所有節點之間很可能出現無法通訊的情況,在節點不能通信時,要保證系統可以繼續正常服務
base【基本可用 ba;軟狀態 s;最終一致 e】
redis實現的分布式鎖。redis分布式鎖的最致命的問題就是無法保證數據的一致性,如果一旦主節點宕機,數據沒有同步到從節點中,會出現再次上鎖的問題,如果業務一定需要數據的一致性在高并發的場景下是不建議選擇redis鎖的實現,可以選擇CP模型的zk或者etcd來實現分布式鎖
三,master-slave
數據備份 & 讀寫分離 & 容災恢復
相關配置
requirepass ***
slaveof <masterip/slaveip>
masterauth <master/slave - password>
相關命令
info replication 查看信息
slaveof 127.0.0.1 6379 - 顯示指定配置當前實例為從節點
slaveof no one - 脫離從節點
哨兵模式 slaveof no one 的自動版本
三個特性:
監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。
提醒(Notification): 當被監控的某個 Redis 服務器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。
自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時, Sentinel 會開始一次自動故障遷移操作
sentinel配置文件:sentinel.conf【必須這樣命名】
sentinel配置文件內容:
port 26379【檢測的端口】
sentinel monitor mymaster 127.0.0.1 6379 2【表示有兩個服務認為主服務掛了才是掛了】
sentinel auth-pass mymaster 123456
daemonize yes【開啟后臺運行模式,linux 上使用】
配置文件:
requirepass / masterauth 建議密碼設置一樣
slaveof 建議不配置,通過命令指定
啟動服務:redis-server.exe sentinel.conf --sentinel
TIPS:主從配置通過命令配置,當master服務宕掉重啟之后,會自動把服務設置為slave,指向之前投票選舉的新master
缺點:
1.切換需要時間丟數據
2.沒有解決 master 寫的壓力
優點:
1.高可用
四,cluster
集群搭建
1,至少有六個節點,三個master,一個master 至少一個slave
2,集群啟動前,把rdb, aof和nodes.conf 文件都刪除了
3,文件配置 端口號修改都不一樣,cluster-enabled yes 開啟
4,創建一盒.sh 腳本【chmod u+x start-all.sh 賦予腳本可執行權限】,把所有啟動的redis 都寫進去,執行
5,此時的節點雖然都啟動成功了,但他們還不在一個集群里面,不能互相發現,測試會報錯:(error) CLUSTERDOWN Hash slot not served
如果你是redis5.0以前的,你需要安裝集群所需的ruby相關依賴
redis5.0及之后的,無需安裝ruby依賴,redis安裝目錄里內置了集群命令行工具 redis-trib ,它是一個 Ruby 程序, 這個程序通過向實例發送特殊命令來完成創建新集群, 檢查集群, 或者對集群進行重新分片工作
命令:redis-cli --cluster create 192.168.93.130:7002 192.168.93.130:7003 192.168.93.130:7004 192.168.93.130:7005 192.168.93.130:7006 192.168.93.130:7001 -a 123456 --cluster-replicas 1
6,客戶端連接:redis-cli -c -h 192.168.119.128 -p 9001
故障轉移
1,集群中的節點會向其它節點發送PING消息(該PING消息會帶著當前集群和節點的信息),如果在規定時間內,沒有收到對應的PONG消息,就把此節點標記為疑似下線。
2,當被分配了slot槽位的主節點中有超過一半的節點都認為此節點疑似下線,那么該節點就真的下線。
3,其它節點收到某節點已經下線的廣播后,把自己內部的集群維護信息也修改為該節點已事實下線。
4,節點資格審查:然后對從節點進行資格審查,每個從節點檢查最后與主節點的斷線時間,如果該值超過配置文件的設置,那么取消該從節點的資格。
5,準備選舉時間:這里使用了延遲觸發機制,主要是給那些延遲低的更高的優先級,延遲低的讓它提前參與被選舉,延遲高的讓它靠后參與被選舉。(延遲的高低是依據之前與主節點的最后斷線時間確定的)
6,選舉投票:當從節點獲取選舉資格后,會向其他帶有slot槽位的主節點發起選舉請求,由它們進行投票,優先級越高的從節點就越有可能成為主節點,當從節點獲取的票數到達一定數值時(如集群內有N個主節點,那么只要有一個從節點獲得了N/2+1的選票即認為勝出),就會替換成為主節點。
7,替換主節點:被選舉出來的從節點會執行slaveof no one把自己的狀態從slave變成master,然后執行clusterDelSlot操作撤銷故障主節點負責的槽,并執行 clusterAddSlot把這些槽分配給自己,之后向集群廣播自己的pong消息,通知集群內所有的節點,當前從節點已變為主節點。
8,接管相關操作:新的主節點接管了之前故障的主節點的槽信息,接收和處理與自己槽位相關的命令請求。
細節配置
master 配置
關閉rdb,備份交給 slave
可以起開aof (當從服務器上開啟aof,那么主服務器就不要開啟了)
slave配置(無配置時,集群管理命令默認前面是主服務器,后面是從服務器)
聲明 slaveof
配置密碼,如果主節點有配置密碼
某一個slave 打開 rdb
配置是否只讀 slave-read-only
Redis集群集群不可用
有A,B,C三個節點的集群,在沒有復制模型的情況下,如果節點B失敗了,那么整個集群就會以為缺少5501-11000這個范圍的槽而不可用。
使用注意
Redis集群目前無法做數據庫選擇,默認在0數據庫
MGET
缺點
數據通過異步復制,不保證數據的強一致性
優點
解決了redis的寫壓力
127.0.0.1:7000>cluster meet 127.0.0.1:7001
五,持久化
Redis的持久化存儲提供兩種方式:RDB與AOF。RDB是默認配置。AOF需要手動開啟
rdb[Redis DataBase]
功能核心:函數rdbSave(生成RDB文件) rdbLoad(從文件加載內存)兩個函數
作用:在指定的時間間隔內將內存中的數據集快照寫入磁盤,它恢復時時將快照文件直接讀到內存里
過程:單獨創建(fork)一個子進程來進行持久化,會先將數據寫入到一個臨時文件中,再用這個臨時文件替換上次持久化好的文件。整個過程中,主進程是不進行任何IO操作的
優勢:適合大規模的數據恢復,對數據完整性和一致性要求不高
劣勢:在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改,fork(分叉)的時候,內存中的數據被克隆了一份,大致2倍的膨脹性需要考慮
如何恢復 - 將備份文件(dump.rdb) 移動到 redis 安裝目錄并啟動服務即可。
命令觸發 - save(會阻塞)命令調度rdbSave函數
BGSAVE:鏡像全量持久化,因為bgsave耗時長,在停機的時候會導致大量丟失數據。可以通過lastsave命令獲取最后一次成功執行快照的時間
配置項
rdbchecksum:在存儲快照后,還可以讓redis使用CRC64算法來進行數據校驗,但是這樣做會增加大約,10%的性能消耗,如果希望獲取到最大的性能提升,可以關閉此功能
rdbcompression:對于存儲到磁盤中的快照,可以設置是否進行壓縮存儲。如果是的話,redis會采用,LZF算法進行壓縮。如果你不想消耗CPU來進行壓縮的話,可以設置為關閉此功能
stop-writes-on-bgsave-error:如果配置成no,表示你不在乎數據不一致或者有其他的手段發現和控制
dbfilename: 文件名稱
dir :文件目錄,aof和rdb文件
AOF【append only file】
作用
以日志的形式來記錄每個寫操作,將Redis執行過的所有寫指令記錄下來(讀操作不記錄),只許追加文件但不可以改寫文件,
redis啟動之初會讀取該文件重新構建數據,redis重啟的話就根據日志文件的內容將寫指令從前到后執行一次以完成數據的恢復工作
劣勢
相同數據集的數據而言aof文件要遠大于rdb文件,恢復速度慢于rdb
aof運行效率要慢于rdb,每秒同步策略效率較好,不同步效率和rdb相同
配置項
appendfilename
“appendonly.aof” 默認的文件名
appendonly no (是否開啟aof持久化)
默認不開啟
appendfsync
always:同步持久化每次write后都會調用fsync(Linux為調用fdatasync)
everysec:出廠默認推薦,異步操作,每秒記錄,每秒調用一次fsync
這種模式性能并不是很糟糕,一般也不會產生毛刺,這歸功于Redis引入了BIO線程,所有fsync操作都異步交給了BIO線程。
no:則write后不會有fsync調用,由操作系統自動調度刷磁盤,性能是最好的
另外,Redis在處理一條命令時,并不立即調用write寫AOF文件,只是將數據寫入到AOF buffer(server.aof_buf)中。調用write和命令處理是分開的,Redis只在每次進入epoll_wait之前做write操作。
no-appendfsync-on-rewrite:
重寫時是否可以運用Appendfsync,用默認no即可,保證數據安全性
auto-aof-rewrite-min-size:
設置重寫的基準值,默認64M
auto-aof-rewrite-percentage:
設置重寫的基準值 percentage百分比,默認100
aof-load-truncated
yes:加載時碰到異常數據,截斷
no:拋異常,需要用redis-check-aof 修復
總結(Which one)
aof文件比rdb更新頻率高,優先使用aof還原數據。
aof比rdb更安全也更大
rdb性能比aof好
建議
1,master 盡量不要任何一種持久化,在slave 中實現
2,RDB文件只用作后備用途,建議只在Slave上持久化RDB文件,而且只要15分鐘備份一次就夠了,只保留save 900 1這條規則
3,開啟aof。代價一是帶來了持續的IO,二是AOF rewrite【rewrite過程中產生的新數據寫到新文件造成的阻塞幾乎是不可避免的,AOF重寫的基礎大小默認值64M太小了,可以設到5G以上
4,如果不Enable AOF ,僅靠Master-Slave Replication 實現高可用性也可以。能省掉一大筆IO也減少了rewrite時帶來的系統波動。代價是如果Master/Slave同時倒掉,會丟失十幾分鐘的數據,新浪微博就選用了這種架構
5,aof文件過大恢復時間過長怎么辦,Redis會定期做aof重寫,壓縮aof文件,可以手動調用壓縮命令
,Redis4.0之后有了混合持久化的功能,將bgsave的全量和aof的增量做了融合處理
6,bgsave的原理是,fork和cow,fork是指redis通過創建子進程來進行bgsave操作,cow指的是copy on write【在不影響寫的基礎上復制數據】
Redis可以使用主從同步,從從同步。第一次同步時,主節點做一次bgsave,并同時將后續修改操作記錄到內存buffer,待完成后將rdb文件全量同步到復制節點,復制節點接受完成后將rdb鏡像加載到內存。加載完成后,再通知主節點將期間修改的操作記錄同步到復制節點進行重放就完成了同步過程
六,redis配置文件
bind
指定本機網卡對應的IP地址
簡單操作 ipconfig 出現的ipv4 地址都可以綁定 和 127.0.0.1,綁定之后只能通過對應ip能訪問
如果我們想限制只有指定的主機可以連接到redis中,我們只能通過防火墻來控制
使用阿里云的安全組,來限制指定的主機連接6379端口
bind 127.0.0.1 只能本機訪問,
bind 192.168.. 同一局域網能訪問
bind 0.0.0.0 能通過本機ip的都能訪問
# bind 表示所有主機都可以
前提:你的服務器必須開放redis的端口
protected-mode
一個安全層,作用:就是只有【本機】可以訪問redis。這個安全層開啟必須滿足三個條件,不然安全層處于關閉狀態
1)protected-mode yes(處于開啟)
2)沒有bind指令。原文:The server is not binding explicitly to a set of addresses using the “bind” directive.
3)沒有設置密碼。原文:No password is configured。
includes
應用外部的*.conf文件
maxmemory
當內存多少時,觸發策略淘汰,默認被注釋,
如果不設置或者設置0,在64位系統下不限制內存,在32位操作系統最多使用3G數據
一般配置為物理內存的3/4,
動態修改內存大小:config get maxmemory;config set maxmemory
查看內存情況:客戶端,info [信息居多] ,或者 info memory
內存滿了,繼續插入會報OOM錯誤
maxmemory-policy
策略淘汰數據
noeviction:don’t expire at all, just return an error on write operations
allkeys-lru:嘗試回收最少使用的鍵(LRU),使得新添加的數據有空間存放
volatile-lru:嘗試回收最少使用的鍵(LRU),但僅限于在過期集合的鍵
allkeys-random:回收隨機的鍵使得新添加的數據有空間存放
volatile-random:回收隨機的鍵使得新添加的數據有空間存放,但僅限于在過期集合的鍵
volatile-ttl:回收在過期集合的鍵,并且優先回收存活時間(TTL)較短的鍵
allkeys-lfu: 按次數使用最少的
volatile-lfu:
LRU (Least recently used) 最近最少使用,如果數據最近被訪問過,那么將來被訪問的幾率也更高
LFU (Least frequently used) 最不經常使用,如果一個數據在最近一段時間內使用次數很少,那么在將來一段時間內被使用的可能性也很小
maxmemory-samples
設置樣本數量,Lru算法和罪行ttl算法都并非是精確的算法,而是估算的,所以你可以設置樣本的大小
redis默認會檢查這么多個key,并選擇其中lru的那個
默認的5可以產生足夠好的結果。10非常接近真正的LRU,但花費更多的CPU。3是非???#xff0c;但不是非常準確。默認不開啟
save
RDB 持久化配置
save
save 900 1【900秒(15分鐘)內有1個更改】
timeout
客戶端空閑N秒后關閉連接(0為禁用/默認)
tcp-keepalive
單位為秒,如果設置為0,則不會進行Keepalive檢測,建議設置成60
loglevel
日志級別,debug、verbose、notice、warning,默認為verbose
logfile
日志名稱, logfile stdout
默認為標準輸出,如果配置Redis為守護進程方式運行,而這里又配置為日志記錄方式為標準輸出,則日志將會發送給/dev/null
tcp-backlog
設置tcp的backlog,backlog其實是一個連接隊列,backlog隊列總和=未完成三次握手隊列 + 已經完成三次握手隊列。
dir
指定本地數據庫存放目錄 dir ./ 當前目錄下
pidfile
pidfile /var/run/redis.pid【這個是記錄redis-server進程的pid,pid 亦即 Process ID】
當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,可以通過pidfile指定
Port
因為6379在手機按鍵上MERZ對應的號碼,而MERZ取自意大利歌女Alessia Merz的名字
maxclients
設置同一時間最大客戶端連接數,默認10000,如果設置 maxclients 0,表示不作限制
當客戶端連接數到達限制時,Redis會關閉新的連接并向客戶端返回max number of clients reached錯誤信息
七,redis配置文件
基本命令
shutdown
keys *
可以掃出指定模式的key列表【keys指令會導致線程阻塞一段時間,線上服務會停頓,直到指令執行完畢,服務才能恢復】
集群,keys a* 只能查詢當前節點列表
scan指令,scan指令可以無阻塞的提取出指定模式的key列表,但是會有一定的重復概率,在客戶端做一次去重就可以了,耗時
Exists : key
ttl: key查看還有多少秒過期,-1表示永不過期,-2表示已過期
expire: key 秒鐘:為給定的key設置過期時間
persist: key(取消過期時間),即設置永久
movekey: 在當前庫移除了
move : 移動key到另一個庫
del: 刪除key
type : 查詢key類型
Select 0 //選擇數據庫
rename
對一個 key 進行改名,那么改名后的 key的生存時間和改名前一樣
改名成另一個帶生存時間的 another_key ,這時舊的 another_key (以及它的生存時間)會被刪除
dbsize 查看當前數據庫的key的數量
flushdb:清空當前庫
Flushall;通殺全部庫
String
set、get
set key val [ex seconds] [px milliseconds] [nx|xx]
strlen:獲取值長度
Incr key:對一個不存在的 key,默認0,并設置key為 1并返回
incrby key num:同 incr 類似
Decr key:對一個不存在 key,默認0,則設置 key 為-1并返回
Decrby key num:同 decr
setex key secondTime v:
setnx key value:如果 key 已經存在,返回 0
Mset:一次設置多個 key 的值,成功返回 ok 表示所有的值都設置了,失敗返回 0 表示沒有任何值被設置。
Mget:一次獲取多個 key 的值,如果對應 key 不存在,則對應返回 nuil。
append:追加 value,返回新字符串值的長度。
getrange/setrange:獲取指定區間范圍內(包含邊界)的值,從零到負一表示全部
msetnx:設置多個不存在的key,如有key有存在,則失敗
getset(先get再set):將給定 key 的值設為 value ,并返回 key 的舊值(oldvalue),先get然后立即set,舊值沒有返回nil
Hash
hset、hget:
hexists : key field 某個值key
hlen:查詢個數
hkeys :查詢所有的鍵
hvals :查詢所有的值
hmset:設置多個鍵對應的值 hmset key field value [field value]
hmget:獲取多個鍵對應的值 hmget key field field
hgetall:獲取所有的鍵值對
hdel:刪除對應的field
hsetnx: 不存在添加
hincrby:設置一個field增加多少
hincrbyfloat:設置一個field增加多少浮點型
List(列表)
列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)
lpush/rpush:左邊 / 右邊 添加數據
lpop/rpop:從隊列左邊右邊彈出元素
llen key:查詢列表長度
lrange key indexS indexE:獲取對應索引的值 0開始,包含開始結束元素
lrem key count val :刪除相同的值多少count,-count 從表尾檢索,0 刪除全部相同value的值
lindex:通過索引獲取列表中的元素
ltrim :ltrim key 開始index 結束index,截取指定范圍的值后再賦值給key
rpoplpush :源列表 目的列表:移除列表的最后一個元素,并將該元素添加到另一個列表并返回
lset key index value:修改對應索引的值
linsert : key before/after 值1 值2,before位于左邊
如果值全移除,對應的鍵也就消失了
鏈表的操作無論是頭和尾效率都極高,但假如是對中間元素進行操作,效率就很慘淡了
Set(集合)
Redis的Set是string類型的無序集合。它是通過HashTable實現實現的,所以添加,刪除,查找的復雜度都是O(1)
sadd :添加 重復的 不會進入
smembers :查出所有的key
sismember :k1 值1 查看是否k1中存在值1
scard : 獲取元素集合的個數
srem:key value 刪除key集合中的value值
spop: key 隨機出棧,刪除
srandmember:srandmember key num ; 隨機取出 n個值,不刪除
smove : key1 key2 值1 從key1中 移走值1 到 key2中
數學集合類
差集 sdiff k1 k2 ; 在第一個中 不在第二個中
交集 sinter k1 k2 ;在第一種也在第二種
并集 sunion k1 k2;在第一種或在第二種
應用場景
微信抽獎小程序【sadd scard spop/srandmember】
微信朋友圈點贊【sadd(id) srem smembers scard sismember】
微博好友關注社交關系
qq內推可能認識的人
Sorted Set(Zset)
增加了一個權重參數score,使得集合中的元素能夠按score進行有序排列。默認升序排列
zadd key score value :添加,值相同覆蓋分數
zrange key indexS indexE:通過索引查找元素,可選是否帶分數,0 -1 查找全部 【withscores】
zrevrange key indexS indexE:逆序通過索引獲取值
zrem key value:刪除指定的值
zcard:返回元素數量
zcount key scoreS scoreE:有個分數范圍返回數量,包括起終分數
zrangebyscore key scoreS socreE [withscores]:
zrevrangebyscore key scoreE scoreS:逆序,通過分數從大到小輸出
zrank key value:獲取下標值
zrevrank key value :作用是逆序獲得下標值
zscore key value 獲取對應的分數
應用場景
抖音熱搜
根據商品銷售對商品進行排序顯示
BITMAP
setbit key offset value(0/1)
getbit key offset
bitcount key [start end]:針對ascii碼來說,set a “ddd”; bitcount a 1 1
bitop operation destkey key… :operation [ or and not xor] not 時只能有一個key
HyperLogLog
pfadd key value
pfcount key
pfmerge destkey key… :合并
在 Redis 里面,每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基 數
GEO
地理相關
事務
multi:開啟事務,redis會將后續的命令逐個放入隊列中,然后使用EXEC命令來原子化執行這個命令系列
exec:執行事務中的所有操作命令
discard:取消事務,放棄執行事務塊中的所有命令
watch key [key…]:監視一個或多個key,如果事務在執行前,這個key(或多個key)被其他命令修改,則事務被中斷,不會執行事務中的任何命令。
unwatch:取消WATCH對所有key的監視。
八,雪崩、擊穿、穿透
緩存穿透:是指數據庫、緩存中都不存在,而用戶不斷得發起請求,導致數據庫壓力過大,甚至嚴重會擊垮數據庫。
1,采用布隆過濾器,使用一個足夠大的bitmap,用于存儲可能訪問的key,不存在的key直接被過濾
2,攔截器,id<=0的直接攔截,基于業務的簡單判斷
3,從cache和db都取不到,可以將key-value寫為key-null,設置較短過期時間,或者該key對應的數據insert了之后清理緩存。
4,對一定不存在的key進行過濾??梢园阉械目赡艽嬖诘膋ey放到一個大的Bitmap中,查詢時通過該bitmap過濾
緩存雪崩:某一時刻大面積key失效,那么在高并發得情況下,所有得請求都會落在DB,對DB造成過大得壓力
1,批量向redis中存放數據時,把每一個得key得失效時間加一個隨機值
2,如果緩存數據庫是分布式部署,將熱點數據均勻分布在不同搞得緩存數據庫中,設置熱點數據永遠不過期
3,在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待
緩存擊穿:指一個Key非常熱點,在不停的扛著大并發,大并發集中對這一個點進行訪問,當這個Key在失效的瞬間,持續的大并發就穿破緩存,直接請求數據庫就像在一個完好無損的桶上鑿開了一個洞。
解決緩存擊穿:設置熱點數據永遠不過期。加互斥鎖
九,問答
為什么要用pipeline?
答,可以將多次IO往返的時間縮減為一次
是否使用過Redis集群,集群的原理是什么?
Redis Sentinal著眼于高可用,在master宕機時會自動將slave提升為master,繼續提供服務
單進程模型來處理客戶端的請求。對讀寫等事件的響應是通過對epoll函數的包裝來做到的。Redis的實際處理速度完全依靠主進程的執行效率
epoll【能顯著提高程序在大量并發連接中只有少量活躍的情況下的系統CPU利用率】
過期Key刪除策略?
不建議使用定時刪除策略【弊端:用一個定時器來負責監視key,過期則自動刪除。雖然內存及時釋放,但是十分消耗CPU資源】
采用定期刪除【每隔100ms,隨機抽查刪除】+ 惰性刪除【獲取時判斷過期就刪除】+ 內存淘汰機制【volatile-lru】
集群時使用 Mget?
如果key 不在一個slots 中,已拋異常【(error) CROSSSLOT Keys in request don’t hash to the same slot】
需要找支持MGET的客戶端,實現方式在客戶端整合數據返回
關于并發?
Redis為單進程單線程模式,采用隊列模式將并發訪問變為串行訪問,消除了傳統數據庫串行控制的開銷,Redis本身沒有鎖的概念,Redis對于多個客戶端連接并不存在競爭
但是在Jedis客戶端對Redis進行并發訪問時會發生連接超時、數據轉換錯誤、阻塞、客戶端關閉連接等問題,這些問題均是由于客戶端連接混亂造成
Redis做異步隊列?
使用list結構作為隊列,rpush生產消息,lpop消費消息。當lpop沒有消息的時候,要適當sleep一會再重試
list還有個指令叫blpop,在沒有消息的時候,它會阻塞住直到消息到來
生產一次消費多次?
pub/sub主題訂閱者模式,可以實現1:N的消息隊列【缺點:在消費者下線的情況下,生產的消息會丟失】
如何實現延時隊列?
使用sortedset,拿時間戳作為score,消息內容作為key調用zadd來生產消息,消費者用zrangebyscore指令獲取N秒之前的數據輪詢進行處理
reids集群為什么有16384個槽?
CRC16算法產生的hash值有16bit,該算法可以產生2^16-=65536個值,redis 集群主節點基本不可能超過1000【太大會導致 ping pong 占用帶寬過高】, 如果槽位為65536,發送心跳信息的消息頭達8k,發送的心跳包過于龐大,16384 2k ,8192 1k,消息頭 myslots[CLUSTER_SLOTS/8] 發送節點負責槽信息,
redis 為什么并發高?
基于內存 和 nio (select 模式)
使用:
redis 做緩存,減少數據庫壓力,提高性能,分布式鎖,解決并發沖突,單點登錄,排行榜,計數器,布隆過濾器,消息隊列,發布訂閱
總結
以上是生活随笔為你收集整理的Redis 互联网开发必看的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 加权平均值与平均值_如何在Excel中计
- 下一篇: 【人类观察所】quot;当代人quot;