緩存的基本原理:?
? ? 實(shí)現(xiàn)客戶端向后端進(jìn)行請(qǐng)求存儲(chǔ)層數(shù)據(jù),插入緩存層,完成數(shù)據(jù)的極速獲取丧诺,此功能可以完成以下方面:? ?
? ? ? ? ? ? 1入桂、快速獲取存儲(chǔ)層數(shù)據(jù)
? ? ? ? ? ? 2、若緩存層沒有數(shù)據(jù)驳阎,則去請(qǐng)求存儲(chǔ)層(穿透查詢)抗愁,存儲(chǔ)層數(shù)據(jù)會(huì)種到緩存層后(回種)馁蒂,再返回客戶端,這樣下次請(qǐng)求同樣數(shù)據(jù)時(shí)可以直接從緩存層獲取到數(shù)據(jù)
? ? ? ? ? ? 3蜘腌、當(dāng)存儲(chǔ)層掛掉或者無法提供服務(wù)時(shí)沫屡,可以讓客戶端的請(qǐng)求直接打到緩存層上,不管是否請(qǐng)求到數(shù)據(jù)撮珠,都直接返回(熔斷)
------------------------------------------------------------------------------------
Memcache和redis的區(qū)別
? ? ? ? Memcache的優(yōu)點(diǎn)是簡(jiǎn)單易用沮脖,且跟hash非常類似,可以直接用過hash這種數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?缺點(diǎn)不支持?jǐn)?shù)據(jù)的持久化芯急、不支持主從同步勺届、不支持主從(sharding)
? ? ? ? Redis的優(yōu)點(diǎn):
? ? ? ? ? ? ? ? ? ? ? ? ? ? 1.支持多種數(shù)據(jù)類型(set,zset娶耍,hash免姿,String,list)
? ? ? ? ? ? ? ? ? ? ? ? ? ? 2.支持?jǐn)?shù)據(jù)持久化
? ? ? ? ? ? ? ? ? ? ? ? ? ? 3.支持主從同步
? ? ? ? ? ? ? ? ? ? ? ? ? ? 4.支持分片(sharding)(redis3.1后支持)
為什么Redis快
? ? ? ? 1.官方提供100000Qps(每秒內(nèi)查詢次數(shù))實(shí)際生產(chǎn)40000Qps左右
? ? ? ? 2.完全基于內(nèi)存的榕酒,大多是內(nèi)存操作胚膊,執(zhí)行效率高
? ? ? ? 3.采用單進(jìn)程、單線程模型的kv數(shù)據(jù)庫(kù) C語言編寫想鹰,數(shù)據(jù)存儲(chǔ)在內(nèi)存中紊婉,讀寫時(shí)不會(huì)受到硬盤的IO限制
? ? ? ? 4.數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,對(duì)數(shù)據(jù)操作也很簡(jiǎn)單(redis不使用表杖挣,不會(huì)對(duì)數(shù)據(jù)進(jìn)行編譯關(guān)聯(lián))
------------------------------------------------------------------------------------
Redis的數(shù)據(jù)類型
? ? ? ? 1.String 最基本的數(shù)據(jù)類型肩榕,二進(jìn)制安全,最大可以存儲(chǔ)512M
? ? ? ? ? ? ? ? ? ? ?保存 set name “redis” 獲取 get name incr(自增1)? ??
? ? ? ? 2.Hash:String元素組成的字典 適用于對(duì)象
? ? ? ? 3.List:列表惩妇,按照String插入順序排序?
? ? ? ? 4.Set:String元素組成的無序集合,通過hash表實(shí)現(xiàn)筐乳,不可重復(fù)
? ? ? ? 5.Sorted Set:通過分?jǐn)?shù)來為集合中的成員做從小到大排序
? ? ? ? 除此之外還有 用于計(jì)數(shù)的HyperLogLog歌殃,用于支持存儲(chǔ)地理位置信息的Geo
如何從海量數(shù)據(jù)中獲取到某一固定前綴的Key
? ? ? ? 1.摸清數(shù)據(jù)量
? ? ? ? 一、使用Keys 一次性返回所有匹配的key? 數(shù)量過大的時(shí)候會(huì)使服務(wù)卡頓
? ? ? ? 二蝙云、使用SCAN cursor 給定游標(biāo)0 然后每次獲取上一次返回游標(biāo)的值傳入下一次查詢氓皱,注意去重(可能游標(biāo)比上一次小)
------------------------------------------------------------------------------------
通過Redis實(shí)現(xiàn)分布式鎖
? ? ? ? 分布式鎖需要解決的問題
? ? ? ? ? ? ? ? 互斥性:任意時(shí)刻只能有一個(gè)客戶端獲取鎖
? ? ? ? ? ? ? ? 安全性:鎖中只能由持有鎖的客戶端刪除勃刨,不能被其他客戶端刪除
? ? ? ? ? ? ? ? 死鎖:獲取鎖的客戶端因?yàn)槟承┰蚨礄C(jī)未能釋放鎖
? ? ? ? ? ? ? ? 容錯(cuò):當(dāng)redis宕機(jī)時(shí) 依然可以獲取到鎖
? ? ? ? SETNX key value:如果key不存在波材,則創(chuàng)建并賦值
? ? ? ? ? ? ? ? 時(shí)間復(fù)雜度:0(1)
? ? ? ? ? ? ? ? 返回值:設(shè)置成功,返回1身隐;設(shè)置失敗廷区,返回0
? ? ? ? EXPIPE key secands?
? ? ? ? ? ? ? ? 設(shè)置key的生存時(shí)間,當(dāng)key過期贾铝,會(huì)被自動(dòng)刪除
? ? ? ? ? ? ? ? 缺點(diǎn):原子性得不到保證 雖然都是原子性隙轻,但是組合在一起不能保證原子性
RedisService redisService = SpringUtils埠帕。getBean(RedisService.class)
long status = redisService.setnx(key,"1");
if( status == 1){
? ? //設(shè)置過期時(shí)間
? ? redisService.expire(key expire)玖绿;
? ? //執(zhí)行獨(dú)占資源邏輯
? ? do0cuppiedWork()敛瓷;
}
? ? ? ? 解決如上無法保證原子性的問題?
? ? ? ? ? ? ? ? 至redis2.6以后 可以使用SET key value [EX sconds][PX milliseconds][NX|XX]
? ? ? ? ? ? ? ? ? ? ? ??EX sconds:設(shè)置鍵的過期時(shí)間 seconds秒
? ? ? ? ? ? ? ? ? ? ? ? PX?milliseconds:設(shè)置過期時(shí)間為millisecond 毫秒
? ? ? ? ? ? ? ? ? ? ? ? NX:只要間不存在時(shí),才對(duì)鍵進(jìn)行設(shè)置操作
? ? ? ? ? ? ? ? ? ? ? ? XX:只在鍵已存在時(shí)斑匪,才對(duì)鍵進(jìn)行設(shè)置操作
? ? ? ? ? ? ? ? ? ? SET操作成功完成時(shí)呐籽,返回OK,否則返回nil
? ? ? ? String result = redisService.set(lockKey, ????????????requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE,expireTime)蚀瘸;
?????????if ("OK".equalks(result)) {
? ? ? ????? //執(zhí)行獨(dú)占資源邏輯
????? ????? do0cuppiedWork()绝淡;
????????}
-------------------------------------------------------------------------------------
如何使用redis做異步隊(duì)列
? ? ? ? 使用list作為隊(duì)列 ,RPUST生產(chǎn)消息苍姜,LPOP消費(fèi)消息
? ? ? ? ? ? 缺點(diǎn):沒有等待隊(duì)列中有值就直接消費(fèi)
? ? ? ? ? ? 彌補(bǔ):可以通過代碼引入Sleep機(jī)制調(diào)用LPOP重試
? ? ? ? BLPOP? key timeout 阻塞知道有消息或者超時(shí)
? ? ? ? ? ? 缺點(diǎn):只能供一個(gè)消費(fèi)者消費(fèi)
? ? ? ? 使用Redis pub/sub:主題訂閱者模式
? ? ? ? ? ? subscribe mytopic? ? 訂閱消息
? ? ? ? ? ? publish mytopic????????發(fā)布消息
? ? ? ? ? ? 缺點(diǎn):無法保證消息一定被接收到
------------------------------------------------------------------------------------
Redis如何做持久化
? ? RDB(快照)持久化:保存某個(gè)時(shí)間點(diǎn)的全量數(shù)據(jù)快照
? ? ? ? redis.conf ->save 900 1 表示900秒內(nèi)有一次寫入操作就執(zhí)行保存快照
? ? ? ? ? ? ? ? ? ? ? ? ? ? save 300 10 表示300秒內(nèi)有10次寫入操作就執(zhí)行保存快照
? ? ? ? ? ? ? ? ? ? ? ? ? ? save 60 10000表示60秒內(nèi)有10000次寫入操作就執(zhí)行保存快照
? ? ? ? ? ? ? ? ? ? ? ? ? ? stop-writes-on-bgsave-error yes 當(dāng)備份進(jìn)程出錯(cuò)的時(shí)候牢酵,主進(jìn)程就停止寫入操作了,可以保證持久化數(shù)據(jù)一致性
? ? ? ? ? ? ? ? ? ? ? ? ? ? rdbcompression yes 壓縮后持久化(建議設(shè)置為no)
? ? ? ? save:阻塞redis服務(wù)器進(jìn)程衙猪,直到RDB文件被創(chuàng)建完畢:
? ? ? ? BGSAVE:Fork出一個(gè)紫禁城出來創(chuàng)建RDB文件馍乙,不阻塞服務(wù)器進(jìn)程
? ? 自動(dòng)化觸發(fā)RDB持久化得方式
? ? ? ? ①根據(jù)redis.conf配置里的save m n 定時(shí)觸發(fā)(使用的是BGSAVE)
? ? ? ? ②主從復(fù)制時(shí),主節(jié)點(diǎn)自動(dòng)觸發(fā)
????????③執(zhí)行Debug Reload
? ? ? ? ④執(zhí)行Shutdown且沒有開啟AOF持久化
缺點(diǎn):內(nèi)存數(shù)據(jù)全量同步垫释,數(shù)據(jù)量大會(huì)由于IO而影響性能
? ? ? ? ? ?可能會(huì)因?yàn)镽edis掛掉而丟失從當(dāng)前至最近一次快照期間的數(shù)據(jù)
? ? AOF持久化:保存寫狀態(tài)
? ? ? ? appendonly yes
? ? ? ? appendfilename “appendonly.aof”
? ? ? ? appendfsync everysec? 寫入方式 always 只要發(fā)生寫操作就寫入aof;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?everysec美妙寫入一次(推薦)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?no交給操作系統(tǒng)決定
????redis4.0后支持RDB-AOF混合持久化方式
? ? ? ? ? ? BGSAVE 做鏡像的全量持久化丝格,AOF做增量持久化
------------------------------------------------------------------------------------
Redis 的同步機(jī)制
????全量同步過程:
? ? ? ? Salve發(fā)送sync命令到Master
? ? ? ? Master啟動(dòng)一個(gè)后臺(tái)進(jìn)程,將Redis中的數(shù)據(jù)快照保存到文件中(BGSAVE)
? ? ? ? Master將保存數(shù)據(jù)快照期間接收的寫命令緩存起來
? ? ? ? Master完成寫文件操作后棵譬,將文件發(fā)送給salve
? ? ? ? 使用新的AOF文件替換掉舊的AOF文件
? ? ? ? Master將這期間手機(jī)的增量寫命令發(fā)送給salve端
? ? 增量同步操作
? ? ? ? Master接收到的用戶指令显蝌,判斷是否需要傳播到Salve
? ? ? ? 將操作記錄追加到AOF文件中
? ? ? ? 將操作傳播到其他Slave:1.對(duì)其主從庫(kù);2.往響應(yīng)緩存寫入指令
? ? ? ? 將緩存中的數(shù)據(jù)發(fā)送給Slave
? ? Redis Sentine(哨兵)
? ? ? ? 解決主從同步Master當(dāng)即后的主從切換問題
? ? ? ? ? ? 監(jiān)控:檢查主從服務(wù)器是否運(yùn)行正常
? ? ? ? ? ? 提醒:通過API向管理員或者其他應(yīng)用程序發(fā)送故障通知
? ? ? ? ? ? 自動(dòng)故障遷移:主從切換(使用投票協(xié)議)
? ? ? ? 流言協(xié)議 Gossip
? ? ? ? ? ? 在雜亂無章中尋求一致
? ? ? ? ? ? ? ? 每個(gè)節(jié)點(diǎn)都隨機(jī)與對(duì)方通信订咸,最終所有節(jié)點(diǎn)裝填達(dá)成一致
? ? ? ? ? ? ? ? 每個(gè)種子節(jié)點(diǎn)定期隨機(jī)向其他節(jié)點(diǎn)發(fā)送節(jié)點(diǎn)列表以及需要傳播的消息
? ? ? ? ? ? ? ? 不保證信息一定會(huì)傳遞給所有節(jié)點(diǎn)曼尊,但是最終會(huì)趨于一致
----------------------------------------------------------------------------------------------------
Redis的集群原理
? ? 從海量數(shù)據(jù)里快速找出所需?
? ? ? ? 分片:按照某種規(guī)則去劃分?jǐn)?shù)據(jù)脏嚷,分散存儲(chǔ)在多個(gè)節(jié)點(diǎn)上
? ? ? ? 常規(guī)的按照哈希劃分無法實(shí)現(xiàn)節(jié)點(diǎn)的動(dòng)態(tài)增減
? ? 一致性哈希算法:對(duì)2^32取模骆撇。將哈希值空間自稱虛擬的圓環(huán)(0=2^32)
? ? ? ? 當(dāng)節(jié)點(diǎn)較少時(shí),hash環(huán)的數(shù)據(jù)傾斜問題(解決方法:使用虛擬節(jié)點(diǎn)映射父叙,通常設(shè)置32個(gè)虛擬節(jié)點(diǎn)以上)