Redis
1臭挽、描述什么是RedisTemplate
RedisTemplate是一個(gè)key和value都是泛型的模板類郑原,一般情況下key為String類型
Spring封裝了RedisTemplate對象,來進(jìn)行對Redis的各種操作,它支持所有Redis原生的api笙以。RedisTemplate位于spring-data-redis包下拳氢。RedisTemplate提供了redis各種操作纬霞、異常處理及序列化凌埂,支持發(fā)布訂閱,并對spring 3.1 cache進(jìn)行了實(shí)現(xiàn)诗芜。
2瞳抓、string結(jié)構(gòu)類型常用命令和應(yīng)用場景
賦值語法:SET KEY_NAME VALUE: (說明:多次設(shè)置name會(huì)覆蓋) (Redis SET 命令用于設(shè)置給定 key 的值埃疫。如果 key 已經(jīng)存儲(chǔ)值, SET 就覆寫舊值孩哑,且無視類型)
取值語法: GET KEY_NAME : Redis GET命令用于獲取指定 key 的值栓霜。如果 key 不存在,返回 nil 横蜒。如果key 儲(chǔ)存的值不是字符串類型胳蛮,返回一個(gè)錯(cuò)誤。 GETRANGE key start end : 用于獲取存儲(chǔ)在指定 key 中字符串的子字符串丛晌。字符串的截取范圍由 start 和 end 兩個(gè)偏移量決定(包括 start 和 end 在內(nèi)) DEL KEY_Name : 刪除指定的KEY仅炊,如果存在,返回值數(shù)字類型茵乱。
STRLEN key : 返回 key 所儲(chǔ)存的字符串值的長度
自增:INCRBY KEY_Name :增量值 Incrby 命令將 key 中儲(chǔ)存的數(shù)字加上指定的增量值 自減:DECYBY KEY_NAME 減值 :DECR 命令將 key 中儲(chǔ)存的數(shù)字減1
應(yīng)用場景:
-1茂洒、String通常用于保存單個(gè)字符串或JSON字符串?dāng)?shù)據(jù)
-2孟岛、因String是二進(jìn)制安全的瓶竭,所以你完全可以把一個(gè)圖片文件的內(nèi)容作為字符串來存儲(chǔ)
-3、計(jì)數(shù)器(常規(guī)key-value緩存應(yīng)用渠羞。常規(guī)計(jì)數(shù):微博數(shù),粉絲數(shù))
3斤贰、hash類型常用命令和應(yīng)用場景
常用命令:
賦值語法:
HSETKEYFIELDVALUE:為指定的KEY,設(shè)定FILD/VALUE
取值語法:
HGETKEYFIELD:獲取存儲(chǔ)在HASH中的值次询,根據(jù)FIELD得到VALUE
刪除語法:
HDELKEYfield1[field2]:刪除一個(gè)或多個(gè)HASH表字段
應(yīng)用場景:
1荧恍、常用于存儲(chǔ)一個(gè)對象
? ? 如一個(gè)人的信息等
4、list類型常用命令和應(yīng)用場景
賦值語法:
LPUSHkeyvalue1[value2]:將一個(gè)或多個(gè)值插入到列表頭部(從左側(cè)添加)
RPUSHkeyvalue1[value2]:在列表中添加一個(gè)或多個(gè)值(從右側(cè)添加)
LPUSHXkeyvalue:將一個(gè)值插入到已存在的列表頭部屯吊。如果列表不在送巡,操作無效
RPUSHXkeyvalue:一個(gè)值插入已存在的列表尾部(最右邊)。如果列表不在盒卸,操作無效骗爆。
取值語法:
LINDEXkeyindex:通過索引獲取列表中的元素
LRANGEkeystartstop:獲取列表指定范圍內(nèi)的元素
刪除語法:
LPOPkey移出并獲取列表的第一個(gè)元素(從左側(cè)刪除)
RPOPkey移除列表的最后一個(gè)元素,返回值為移除的元素(從右側(cè)刪除)
應(yīng)用場景:
1蔽介、對數(shù)據(jù)量大的集合數(shù)據(jù)刪減2摘投、任務(wù)隊(duì)列**
列表數(shù)據(jù)顯示、關(guān)注列表虹蓄、粉絲列表犀呼、留言評價(jià)等…分頁、熱點(diǎn)新聞薇组、消息列表
5外臂、set類型常用命令和應(yīng)用場景
賦值語法:
SADDkeymember1[member2]
取值語法:
SCARDkey:獲取集合的成員數(shù)
SMEMBERSkey:返回集合中的所有成員
刪除語法:
SPOPkey[count]:移除并返回集合中的一個(gè)隨機(jī)元素
應(yīng)用場景:
? ? 對兩個(gè)集合間的數(shù)據(jù)[計(jì)算]進(jìn)行交集、并集律胀、差集運(yùn)算
? ? 共同關(guān)注宋光、共同喜好挑童、二度好友、統(tǒng)計(jì)訪問網(wǎng)站的所有獨(dú)立IP跃须、存取某天的活躍用戶列表
6站叼、zset/hyperloglog類型常用命令和應(yīng)用場景
ZADDkeyscore1member1[score2member2]:向有序集合添加一個(gè)或多個(gè)成員,或者更新已存在成員的分?jǐn)?shù)
ZCARDkey:獲取有序集合的成員數(shù)
ZCOUNTkeyminmax:計(jì)算在有序集合中指定區(qū)間分?jǐn)?shù)的成員數(shù)
DELkey:移除集合
應(yīng)用場景:
? ? 排行榜
HyperLogLog是用來做基數(shù)統(tǒng)計(jì)的算法
PFADDkeyelement[element...]:添加指定元素到HyperLogLog中
PFCOUNTkey[key...]:返回給定HyperLogLog的基數(shù)估算值
PFMERGEdestkeysourcekey[sourcekey...]:將多個(gè)HyperLogLog合并為一個(gè)HyperLogLog
應(yīng)用場景:
? ? 統(tǒng)計(jì)注冊IP數(shù)
? ? 統(tǒng)計(jì)每日訪問IP數(shù)
? ? 統(tǒng)計(jì)頁面實(shí)時(shí)UV數(shù)
? ? 統(tǒng)計(jì)在線用戶數(shù)
? ? 統(tǒng)計(jì)用戶每天搜索不同詞條的個(gè)數(shù)
? ? 統(tǒng)計(jì)真實(shí)文章閱讀數(shù)
7菇民、描述什么是Redis事務(wù)尽楔?
Redis 事務(wù)可以一次執(zhí)行多個(gè)命令,(按順序地串行化執(zhí)行第练,執(zhí)行中不會(huì)被其它命令插入阔馋,不許加塞)
兩個(gè)重要的保證: 1. Redis會(huì)將一個(gè)事務(wù)中的所有命令序列化,然后按順序執(zhí)行 2. 執(zhí)行中不會(huì)被其它命令插入娇掏,不許出現(xiàn)加塞行為
8呕寝、Redis持久化機(jī)制有哪些,以及區(qū)別
RDB一定時(shí)間取存儲(chǔ)文件婴梧,AOF默認(rèn)每秒去存儲(chǔ)歷史命令下梢,
RDB持久化是指在指定的時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤
AOF持久化以日志的形式記錄服務(wù)器所處理的每一個(gè)寫、刪除操作塞蹭,查詢操作不會(huì)記錄孽江,以文本的方式記錄,可以打開文件看到詳細(xì)的操作記錄番电,并追加到文件中岗屏。
9、描述Redis緩存雪崩漱办?解決方案
緩存大量失效的時(shí)候这刷,引發(fā)大量查詢數(shù)據(jù)庫。
解決辦法:? 用鎖/分布式鎖或者隊(duì)列串行訪問 緩存失效時(shí)間均勻分布 數(shù)據(jù)預(yù)熱
10娩井、描述Redis緩存穿透暇屋?解決方案
緩存穿透是指查詢一個(gè)一定不存在的數(shù)據(jù),由于緩存是不命中時(shí)需要從數(shù)據(jù)庫查詢撞牢,查不到數(shù)據(jù)則不寫入緩存率碾,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請求都要到數(shù)據(jù)庫去查詢,造成緩存穿透屋彪。
解決辦法: 1所宰、緩存空結(jié)果,但他的過期時(shí)間很短畜挥。 2仔粥、利用布隆過濾器,,攔截這個(gè)一定不存在的數(shù)據(jù)
11躯泰、對于熱點(diǎn)key谭羔,有什么需要注意的?解決方案
熱點(diǎn)key: 某個(gè)key訪問非常頻繁麦向,當(dāng)key失效的時(shí)候有大量線程來構(gòu)建緩存瘟裸,導(dǎo)致負(fù)載增加,且這是會(huì)有大量請求去查詢數(shù)據(jù)庫诵竭,可能掛掉數(shù)據(jù)庫话告,使系統(tǒng)崩潰。
解決方案:1 使用鎖卵慰,單機(jī)用synchronized,lock等沙郭,分布式用分布式鎖。2 不設(shè)置key緩存過期時(shí)間裳朋,而是設(shè)置在key對應(yīng)的value里病线。如果檢測到存的時(shí)間超過過期時(shí)間則異步更新緩存。3在value設(shè)置一個(gè)比過期時(shí)間t0小的過期時(shí)間值t1鲤嫡,當(dāng)t1過期的時(shí)候送挑,延長t1并做更新緩存操作。4設(shè)置標(biāo)簽緩存泛范,標(biāo)簽緩存設(shè)置過期時(shí)間让虐,標(biāo)簽緩存過期后紊撕,需異步地更新實(shí)際緩存
12罢荡、Redis缺點(diǎn)是什么?說出解決方案
缺點(diǎn): 耗內(nèi)存 解決方案: 1对扶、加內(nèi)存 2区赵、給數(shù)據(jù)key加上過期時(shí)間 3、配置redis數(shù)據(jù)淘汰策略
13浪南、你的項(xiàng)目中笼才,是如何將Redis和數(shù)據(jù)庫數(shù)據(jù)進(jìn)行同步的?
redis同步到數(shù)據(jù)庫: 對于一部分重要的數(shù)據(jù)采用 異步隊(duì)列 的方式同步到數(shù)據(jù)庫络凿,其他的數(shù)據(jù)采用 定時(shí)同步 到數(shù)據(jù)庫
數(shù)據(jù)庫同步到redis:數(shù)據(jù)預(yù)熱`及 加鎖排隊(duì):
先進(jìn)行數(shù)據(jù)預(yù)熱骡送,將數(shù)據(jù)先一步加載到緩存中,
對于數(shù)據(jù)庫中新添加的數(shù)據(jù)采用加鎖排隊(duì)的方式加載數(shù)據(jù)絮记,防止緩存穿透摔踱、雪崩等異常
(一)緩存和數(shù)據(jù)庫雙寫一致性問題 解決方案: 1、實(shí)時(shí)同步 2怨愤、異步隊(duì)列 3派敷、使用阿里的同步工具canal 4、采用UDF自定義函數(shù)的方式(二)緩存穿透 解決辦法:? ? ? 持久層查詢不到就緩存空結(jié)果,查詢時(shí)先判斷緩存中是否exists(key) ,如果有直接返回空篮愉,沒有則查詢后返回腐芍,注意insert時(shí)需清除查詢的key,否則即便DB中有值也查詢不到(當(dāng)然也可以設(shè)置空緩存的過期時(shí)間): 1试躏、不管數(shù)據(jù)實(shí)際上存不存在猪勇,我們都把這個(gè)鍵存到緩存中(有效期設(shè)置的短一些,比如一分鐘到三分鐘)颠蕴,然后值設(shè)置為一個(gè)特定值埠对,業(yè)務(wù)中如果獲取到的結(jié)果是這個(gè)特定值,則報(bào)錯(cuò)返回裁替。
项玛、 2、是使用 redis 的布隆過濾器(Bloom Filter)弱判,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中襟沮,一個(gè)一定不存在的數(shù)據(jù)會(huì)被 這個(gè)bitmap攔截掉,從而避免了對底層存儲(chǔ)系統(tǒng)的查詢壓力昌腰。
(二)緩存雪崩問題 解決方案: 用鎖/分布式鎖或者隊(duì)列串行訪問 緩存失效時(shí)間均勻分布 1 加鎖排隊(duì). 限流-- 限流算法. 2 數(shù)據(jù)預(yù)熱(三)緩存擊穿問題 解決方案: 1 使用鎖开伏,單機(jī)用synchronized,lock等,分布式用分布式鎖遭商。 2 緩存過期時(shí)間不設(shè)置固灵,而是設(shè)置在key對應(yīng)的value里。如果檢測到存的時(shí)間超過過期時(shí)間則異步更新緩存劫流。 3在value設(shè)置一個(gè)比過期時(shí)間t0小的過期時(shí)間值t1巫玻,當(dāng)t1過期的時(shí)候,延長t1并做更新緩存操作祠汇。 4設(shè)置標(biāo)簽緩存仍秤,標(biāo)簽緩存設(shè)置過期時(shí)間,標(biāo)簽緩存過期后可很,需異步地更新實(shí)際緩存
(四)緩存的并發(fā)競爭問題 解決方案: (1)如果對這個(gè)key操作诗力,不要求順序這種情況下,準(zhǔn)備一個(gè)分布式鎖我抠,大家去搶鎖苇本,搶到鎖就做set操作即可,比較簡單菜拓。 (2)如果對這個(gè)key操作瓣窄,要求順序假設(shè)有一個(gè)key1,系統(tǒng)A需要將key1設(shè)置為valueA,系統(tǒng)B需要將key1設(shè)置為valueB,系統(tǒng)C需要將key1設(shè)置為valueC.期望按照key1的value值按照 valueA-->valueB-->valueC的順序變化。這種時(shí)候我們在數(shù)據(jù)寫入數(shù)據(jù)庫的時(shí)候尘惧,需要保存一個(gè)時(shí)間戳