Redis简单介绍
一、Redis基礎(chǔ)信息
1.1 redis數(shù)據(jù)類型和底層數(shù)據(jù)結(jié)構(gòu)的對應關(guān)系
1.2 數(shù)據(jù)結(jié)構(gòu)的時間復雜度
1.3 為什么單線程Redis能那么快?
1.4 redis的持久化
a. AOF日志
優(yōu)點: 1.寫后日志,避免記錄錯誤命令的情況2.不阻塞當前寫操作。 缺點:1.剛執(zhí)行完一個命令,還沒有來得及記日志就宕機,有丟失數(shù)據(jù)風險。2.AOF雖然避免了對當前命令的阻塞,但可能會給下一個操作帶來阻塞風險。兩個風險都是和AOF寫回磁盤的時機相關(guān),因此產(chǎn)生了三種回寫策略
Always:同步寫回,每個寫命令執(zhí)行完,立馬同步的將日志寫回磁盤 Everysec: 每秒寫回,每個寫命令執(zhí)行完,只是先把日志寫到AOF文件的內(nèi)存緩沖區(qū),每隔一秒把緩沖區(qū)的內(nèi)容寫入磁盤 No: 操作系統(tǒng)控制的寫回,每個寫命令執(zhí)行完,只是先把日志寫到AOF文件的內(nèi)存緩沖區(qū),由操作系統(tǒng)決定何時將緩沖區(qū)內(nèi)容寫回磁盤回寫策略的優(yōu)缺點
AOF重寫機制:
AOF重寫機制就是在重寫時,Redis根據(jù)數(shù)據(jù)庫的現(xiàn)狀創(chuàng)建一個新的AOF文件 作用:避免日志太大,不阻塞主線程由后臺線程bgrewriteaof子進程來完成b. RDB快照(內(nèi)存快照)
1. 給那些內(nèi)存數(shù)據(jù)做快照? Redis的數(shù)據(jù)都在內(nèi)存中,為了提供所有數(shù)據(jù)的可靠性保證,執(zhí)行的是全量快照,把內(nèi)存中所有的數(shù)據(jù)都寫入磁盤中。 2. RDB文件的生成是否會阻塞主線程?a.save: 在主線程中執(zhí)行,會導致阻塞;b.bgsave: 創(chuàng)建一個子進程,專門用于寫入RDB文件,避免了主線程的阻塞,這也是Redis RDB文件生成的默認配置。優(yōu)點: 1.快照的恢復速度快 缺點:快照的頻率不好把握,太低可能丟失數(shù)據(jù)量大,太高產(chǎn)生額外的性能開銷 Redis 4.0中提出了一個混合使用AOF日志和內(nèi)存快照1.5 數(shù)據(jù)同步
主從模式:
當我們啟動多個Redis實例的時候,它們相互之間就可以通過replicaof(Redis 5.0之前使用slaveof)命令形成主庫和從庫的關(guān)系,之后會按照三個階段完成數(shù)據(jù)的第一次同步
同步的耗時操作:
1. 生成RDB文件 2. 傳輸RDB文件主從從模式:
1.7 哨兵機制:主庫掛了,如何不間斷服務(wù)?
哨兵其實就是一個運行在特殊模式下的Redis進程,主從庫實例運行的同時,它也在運行。哨兵主要負責的就是三個任務(wù):監(jiān)控、選主(選擇主庫)和通知 。 哨兵機制實現(xiàn)了主從庫的自動切換:
監(jiān)控主庫運行狀態(tài),并判斷主庫是否客觀下線; 在主庫客觀下線后,選取新主庫; 選出新主庫后,通知從庫和客戶端客戶端只能把寫失敗的請求先緩存起來或?qū)懭胂㈥犃兄虚g件中,等哨兵切換完主從后,再把這些寫請求發(fā)給新的主庫,但這種場景只適合對寫入請求返回值不敏感的業(yè)務(wù),而且還需要業(yè)務(wù)層做適配,另外主從切換時間過長,也會導致客戶端或消息隊列中間件緩存寫請求過多,切換完成之后重放這些請求的時間變長。
1.8 哨兵集群:哨兵掛了,主從庫還能切換嗎?
對于主從切換,當然不是哪個哨兵想執(zhí)行就可以執(zhí)行的,否則就亂套了。所以,這就需要哨兵集群在判斷了主庫“客觀下線”后,經(jīng)過投票仲裁,選舉一個Leader出來,由它負責實際的主從切換,即由它來完成新主庫的選擇以及通知從庫與客戶端。
1.9 切片集群:數(shù)據(jù)增多了,是該加內(nèi)存還是加實例
切片集群是一種保存大量數(shù)據(jù)的通用機制 在應對數(shù)據(jù)量擴容時,雖然增加內(nèi)存這種縱向擴展的方法簡單直接,但是會造成數(shù)據(jù)庫的內(nèi)存過大,導致性能變慢。Redis切片集群提供了橫向擴展的模式,也就是使用多個實例,并給每個實例配置一定數(shù)量的哈希槽,數(shù)據(jù)可以通過鍵的哈希值映射到哈希槽,再通過哈希槽分散保存到不同的實例上。這樣做的好處是擴展性好,不管有多少數(shù)據(jù),切片集群都能應對。
2.0 String內(nèi)存開銷大
除了記錄實際數(shù)據(jù),String類型還需要額外的內(nèi)存空間記錄數(shù)據(jù)長度、空間使用等信息,這些信息也叫作元數(shù)據(jù)。當實際保存的數(shù)據(jù)較小時,元數(shù)據(jù)的空間開銷就顯得比較大。
String類型就會用簡單動態(tài)字符串
buf:字節(jié)數(shù)組,保存實際數(shù)據(jù)。為了表示字節(jié)數(shù)組的結(jié)束,Redis會自動在數(shù)組最后加一個“\0”,這就會額外占用1個字節(jié)的開銷。
len:占4個字節(jié),表示buf的已用長度。
alloc:也占個4字節(jié),表示buf的實際分配長度,一般大于len。
2.1 集合統(tǒng)計
集合類型常見的四種統(tǒng)計模式,包括聚合統(tǒng)計、排序統(tǒng)計、二值狀態(tài)統(tǒng)計和基數(shù)統(tǒng)計
聚合統(tǒng)計(Set):Set的差集、并集和交集的計算復雜度較高,在數(shù)據(jù)量較大的情況下,如果直接執(zhí)行這些計算,會導致Redis實例阻塞。所以,我給你分享一個小建議:你可以從主從集群中選擇一個從庫,讓它專門負責聚合計算,或者是把數(shù)據(jù)讀取到客戶端,在客戶端來完成聚合統(tǒng)計,這樣就可以規(guī)避阻塞主庫實例和其他從庫實例的風險了。排序統(tǒng)計(sorted set):有序集合List是按照元素進入List的順序進行排序的,而Sorted Set可以根據(jù)元素的權(quán)重來排序 二值狀態(tài)統(tǒng)計(BitMap):Bitmap本身是用String類型作為底層數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的一種統(tǒng)計二值狀態(tài)的數(shù)據(jù)類型指集合元素的取值就只有0和1兩種。在簽到打卡的場景中 基數(shù)統(tǒng)計():基數(shù)統(tǒng)計就是指統(tǒng)計一個集合中不重復的元素個數(shù)2.2 Redis的簡單事務(wù)
MULTI:表示一系列原子性操作的開始。收到這個命令后,Redis就知道,接下來再收到的命令需要放到一個內(nèi)部隊列中,后續(xù)一起執(zhí)行,保證原子性 EXEC:表示一系列原子性操作的結(jié)束。一旦Redis收到了這個命令,就表示所有要保證原子性的命令操作都已經(jīng)發(fā)送完成了。 此時,Redis開始執(zhí)行剛才放到內(nèi)部隊列中的所有命令操作。2.3 基于redis實現(xiàn)消息隊列
消息隊列在存取消息的三個需求:
a. 基于List實現(xiàn)消息隊列解決方案
List本身就是按先進先出的順序?qū)?shù)據(jù)進行存取的,能滿足消息保序的需求. LPUSH:把要發(fā)送的消息依次寫入List RPOP: 從List的另一端依次讀取消息并進行處理 BRPOP: 阻塞式讀取,客戶端在沒有讀到隊列數(shù)據(jù)時,自動阻塞,直到有新的數(shù)據(jù)寫入隊列,再開始讀取新數(shù)據(jù) BRPOPLPUSH: 讓消費者程序從一個List中讀取消息,同時,Redis會把這個消息再插入到另一個List(可以叫作備份List)留存。 這樣一來,如果消費者程序讀了消息但沒能正常處理,等它重啟后,就可以從備份List中重新讀取消息并進行處理了 List類型并不支持消費組的實現(xiàn)b. 基于Streams的消息隊列解決方案
Streams是Redis專門為消息隊列設(shè)計的數(shù)據(jù)類型,它提供了豐富的消息隊列操作命令。
2.4 Redis的阻塞點
a. 和客戶端交互時的阻塞點1. 集合全量查詢和聚合操作(復雜度通常為O(N))2. bigkey刪除操作就是Redis的第二個阻塞點 (釋放內(nèi)存,把釋放掉的內(nèi)存塊插入一個空閑內(nèi)存塊的鏈表)3. 清空數(shù)據(jù)庫 b. 和磁盤交互時的阻塞點4. AOF日志同步寫 c. 主從節(jié)點交互時的阻塞點 5. 加載RDB文件 d. 切片集群實例交互時的阻塞點2.5 redis緩存的淘汰策略
noeviction: 寫滿了,再有寫請求來時,Redis不再提供服務(wù) volatile-ttl: 根據(jù)過期時間的先后進行刪除 volatile-random: 設(shè)置了過期時間的鍵值對中,進行隨機刪除 volatile-lru: 使用LRU算法篩選設(shè)置了過期時間的鍵值對(最近最少使用) volatile-lfu: 使用LFU算法選擇設(shè)置了過期時間的鍵值對(最不經(jīng)常使用) allkeys-random: 從所有鍵值對中隨機選擇并刪除數(shù)據(jù) allkeys-lru: 使用LRU算法在所有數(shù)據(jù)中進行篩選 allkeys-lfu: 使用LFU算法在所有數(shù)據(jù)中進行篩選2.6 redis緩存常見問題及解決方案
2.7 緩存污染怎么辦?
1. 什么緩存污染? 有些數(shù)據(jù)被訪問的次數(shù)非常少,甚至只會被訪問一次。當這些數(shù)據(jù)服務(wù)完訪問請求后,如果還繼續(xù)留存在緩存中的話,就只會白白占用緩存空間 2. 如何解決緩存污染問題? 淘汰策略: LRU策略和LFU策略 隨機淘汰策略:避免緩存污染效果差2.8 Redis無鎖原子操作
1. 把多個操作在Redis中實現(xiàn)成一個操作,也就是單命令操作; 2. 把多個操作寫到一個Lua腳本中,以原子性方式執(zhí)行單個Lua腳本。數(shù)據(jù)修改時可能包含多個操作,讀數(shù)據(jù)、數(shù)據(jù)增減、寫回數(shù)據(jù)三個操作,這顯然就不是單個命令操作。 1. Redis提供了INCR/DECR命令,把這三個操作轉(zhuǎn)變?yōu)橐粋€原子操作 2. Lua腳本2.9 Redis實現(xiàn)分布式鎖
單命令操作實現(xiàn)加鎖SETNX: 在執(zhí)行時會判斷鍵值對是否存在,如果不存在,就設(shè)置鍵值對的值,如果存在,就不做任何設(shè)置DEL命令刪除鎖變量 給鎖變量設(shè)置一個過期時間, 避免在處理業(yè)務(wù)時產(chǎn)生異常,無法釋放鎖變量。 基于多個Redis節(jié)點實現(xiàn)高可靠的分布式鎖: Redlock算法的基本思路,是讓客戶端和多個獨立的Redis實例依次請求加鎖,如果客戶端能夠和半數(shù)以上的實例成功地完成加鎖操作, 那么我們就認為,客戶端成功地獲得分布式鎖了,否則加鎖失敗3.0 Redis的事務(wù)實現(xiàn)
事務(wù)的ACID屬性是我們使用事務(wù)進行正確操作的基本要求
Redis的事務(wù)機制可以保證一致性和隔離性 無法保證持久性 當事務(wù)中使用的命令語法有誤時,原子性得不到保證,在其它情況下,事務(wù)都可以原子性執(zhí)行。3.1 Redis6.0新特性
3.2 Redis與其他緩存數(shù)據(jù)庫比較
?
3.3 Redis的學習路線
redis學習推薦書籍
總結(jié)
- 上一篇: Scapy:局域网MAC地址扫描脚本
- 下一篇: spark-2.1.0 集群安装