Redis 的持久化機(jī)制使得內(nèi)存中的數(shù)據(jù)能夠持久化到磁盤虑绵,解決內(nèi)存數(shù)據(jù)掉電易失的問題,而且Redis是一款中間件祖乳,無需依賴jvm
1遥皂、Redis支持哪幾種數(shù)據(jù)類型力喷?
字符串String、字典Hash演训、列表List弟孟、集合Set、有序集合SortedSet; 如果你是Redis中高級(jí)用戶仇祭,還需要加上下面幾種數(shù)據(jù)結(jié)構(gòu)HyperLogLog披蕉、Geo、Pub/Sub乌奇。
? String字符串:
格式: set key value
string類型是二進(jìn)制安全的没讲。意思是redis的string可以包含任何數(shù)據(jù)。比如jpg圖片或者序列化的對(duì)象 礁苗。
string類型是Redis最基本的數(shù)據(jù)類型爬凑,一個(gè)鍵最大能存儲(chǔ)512MB。
? Hash(哈希)
格式: hmset name ?key1 value1 key2 value2
Redis hash 是一個(gè)鍵值(key=>value)對(duì)集合试伙。
Redis hash是一個(gè)string類型的field和value的映射表嘁信,hash特別適合用于存儲(chǔ)對(duì)象。
? List(列表)
Redis 列表是簡(jiǎn)單的字符串列表疏叨,按照插入順序排序潘靖。你可以添加一個(gè)元素到列表的頭部(左邊)或者尾部(右邊)
格式: lpush ?name ?value
在 key 對(duì)應(yīng) list 的頭部添加字符串元素
格式: rpush ?name ?value
在 key 對(duì)應(yīng) list 的尾部添加字符串元素
格式: lrem name ?index
key 對(duì)應(yīng) list 中刪除 count 個(gè)和 value 相同的元素
格式: llen name
返回 key 對(duì)應(yīng) list 的長度
? Set(集合)
格式: sadd ?name ?value
Redis的Set是string類型的無序集合。
集合是通過哈希表實(shí)現(xiàn)的蚤蔓,所以添加卦溢,刪除,查找的復(fù)雜度都是O(1)。
? zset(sorted set:有序集合)
格式: zadd ?name score value
Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復(fù)的成員单寂。
不同的是每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè)double類型的分?jǐn)?shù)贬芥。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。
zset的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)宣决。
2蘸劈、什么是緩存穿透
一般的緩存系統(tǒng),都是按照key去緩存查詢,如果不存在對(duì)應(yīng)的value,就應(yīng)該去數(shù)據(jù)庫查詢。一些惡意的請(qǐng)求會(huì)故意大量查詢不存在的key,就會(huì)對(duì)數(shù)據(jù)庫造成很大的壓力尊沸。這就叫做緩存穿透威沫。簡(jiǎn)單的說就是故意避開緩存去數(shù)據(jù)庫查詢數(shù)據(jù)。椒丧。場(chǎng)景:當(dāng)客戶端發(fā)起查詢時(shí)壹甥,緩存中沒有就會(huì)去查庫,庫里也沒有壶熏,就會(huì)返回給客戶端錯(cuò)誤信息句柠。這樣是沒問題的,看起來邏輯是完美的棒假,但是這里存在一個(gè)漏洞溯职,那就是無論什么樣的Key過來查,都接受它的請(qǐng)求帽哑,這就可能會(huì)被黑客抓住谜酒,發(fā)起大量請(qǐng)求,并且Key都是系統(tǒng)中沒有的妻枕,庫里也查不到對(duì)應(yīng)的值僻族,這樣的Key稱之為非法Key。那么當(dāng)大量這樣的請(qǐng)求過來時(shí)是不是都不會(huì)命中Redis屡谐,然后都會(huì)打到DB上述么,當(dāng)DB瞬時(shí)接收到如此多的連接時(shí),DB就有可能撐不住愕掏,掛掉度秘。這就是存在的一個(gè)隱藏的漏洞,黑客或者惡意攻擊者就會(huì)抓住這一點(diǎn)攻擊你的系統(tǒng)饵撑,使你的系統(tǒng)癱瘓剑梳。
? 采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中滑潘,一個(gè)一定不存在的數(shù)據(jù)會(huì)被 這個(gè)bitmap攔截掉垢乙,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力。
? 另外也有一個(gè)更為簡(jiǎn)單粗暴的方法(我們采用的就是這種)语卤,如果一個(gè)查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在追逮,還是系統(tǒng)故障)蓖租,我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過期時(shí)間會(huì)很短羊壹,最長不超過五分鐘。
3齐婴、什么是緩存擊穿
是針對(duì)緩存中沒有但數(shù)據(jù)庫有的數(shù)據(jù)油猫。場(chǎng)景是,當(dāng)Key失效后柠偶,假如瞬間突然涌入大量的請(qǐng)求情妖,來請(qǐng)求同一個(gè)Key,這些請(qǐng)求不會(huì)命中Redis诱担,都會(huì)請(qǐng)求到DB毡证,導(dǎo)致數(shù)據(jù)庫壓力過大,甚至扛不住蔫仙,掛掉料睛。解決辦法:
? 設(shè)置熱點(diǎn)Key,自動(dòng)檢測(cè)熱點(diǎn)Key摇邦,將熱點(diǎn)Key的過期時(shí)間加大或者設(shè)置為永不過期恤煞,或者設(shè)置為邏輯上永不過期,具體設(shè)置方法待會(huì)說施籍。
? 加互斥鎖居扒。當(dāng)發(fā)現(xiàn)沒有命中Redis,去查數(shù)據(jù)庫的時(shí)候丑慎,在執(zhí)行更新緩存的操作上加鎖喜喂,誰拿到鎖誰去更新,同時(shí)在拿到鎖之后先從緩存再獲取一次如果有就返回竿裂,沒有就查庫然后更新玉吁。(雙重校驗(yàn))
4、什么是緩存雪崩
緩存雪崩是指緩存中數(shù)據(jù)大批量到過期時(shí)間铛绰,而查詢數(shù)據(jù)量巨大诈茧,引起數(shù)據(jù)庫壓力過大甚至down機(jī)。和緩存擊穿不同的是, 緩存擊穿指并發(fā)查同一條數(shù)據(jù)捂掰,緩存雪崩是不同數(shù)據(jù)都過期了敢会,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫。簡(jiǎn)單地說就是緩存大量過期去數(shù)據(jù)庫查詢數(shù)據(jù)这嚣。
解決辦法:
? 緩存數(shù)據(jù)的過期時(shí)間設(shè)置隨機(jī)鸥昏,防止同一時(shí)間大量數(shù)據(jù)過期現(xiàn)象發(fā)生。
? 如果緩存數(shù)據(jù)庫是分布式部署姐帚,將熱點(diǎn)數(shù)據(jù)均勻分布在不同搞得緩存數(shù)據(jù)庫中吏垮。
? 設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過期。
5、Redis有哪些架構(gòu)模式膳汪?各有什么特點(diǎn)
? 單機(jī)版
特點(diǎn):
簡(jiǎn)單
問題:
1唯蝶、內(nèi)存容量有限
2、處理能力有限
3遗嗽、無法高可用粘我。
? 主從復(fù)制
Redis 的復(fù)制(replication)功能允許用戶根據(jù)一個(gè) Redis 服務(wù)器來創(chuàng)建任意多個(gè)該服務(wù)器的復(fù)制品,其中被復(fù)制的服務(wù)器為主服務(wù)器(master)痹换,而通過復(fù)制創(chuàng)建出來的服務(wù)器復(fù)制品則為從服務(wù)器(slave)征字。只要主從服務(wù)器之間的網(wǎng)絡(luò)連接正常,主從服務(wù)器兩者會(huì)具有相同的數(shù)據(jù)娇豫,主服務(wù)器就會(huì)一直將發(fā)生在自己身上的數(shù)據(jù)更新同步 給從服務(wù)器匙姜,從而一直保證主從服務(wù)器的數(shù)據(jù)相同。
特點(diǎn):
1冯痢、master/slave 角色
2氮昧、master/slave 數(shù)據(jù)相同
3、降低 master 讀壓力在轉(zhuǎn)交從庫
問題:
無法保證高可用
沒有解決 master 寫的壓力
? 哨兵
Redis sentinel 是一個(gè)分布式系統(tǒng)中監(jiān)控 redis 主從服務(wù)器系羞,并在主服務(wù)器下線時(shí)自動(dòng)進(jìn)行故障轉(zhuǎn)移郭计。其中三個(gè)特性:
監(jiān)控(Monitoring):? ?Sentinel ?會(huì)不斷地檢查你的主服務(wù)器和從服務(wù)器是否運(yùn)作正常。
提醒(Notification):當(dāng)被監(jiān)控的某個(gè) Redis 服務(wù)器出現(xiàn)問題時(shí)椒振, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知昭伸。
自動(dòng)故障遷移(Automatic failover):當(dāng)一個(gè)主服務(wù)器不能正常工作時(shí), Sentinel 會(huì)開始一次自動(dòng)故障遷移操作澎迎。
特點(diǎn):
1庐杨、保證高可用
2、監(jiān)控各個(gè)節(jié)點(diǎn)
3夹供、自動(dòng)故障遷移
缺點(diǎn):主從模式灵份,切換需要時(shí)間丟數(shù)據(jù)
沒有解決 master寫的壓力
? 集群(proxy 型)
Twemproxy 是一個(gè) Twitter 開源的一個(gè) redis 和 memcache 快速/輕量級(jí)代理服務(wù)器;Twemproxy 是一個(gè)快速的單線程代理程序哮洽,支持 Memcached ASCII 協(xié)議和 redis 協(xié)議填渠。
特點(diǎn):
1、多種 hash 算法:MD5鸟辅、CRC16氛什、CRC32、CRC32a匪凉、hsieh枪眉、murmur、Jenkins
2再层、支持失敗節(jié)點(diǎn)自動(dòng)刪除
3贸铜、后端 Sharding 分片邏輯對(duì)業(yè)務(wù)透明堡纬,業(yè)務(wù)方的讀寫方式和操作單個(gè) Redis 一致
缺點(diǎn):
增加了新的 proxy,需要維護(hù)其高可用蒿秦。
failover 邏輯需要自己實(shí)現(xiàn)烤镐,其本身不能支持故障的自動(dòng)轉(zhuǎn)移可擴(kuò)展性差,進(jìn)行擴(kuò)縮容都需要手動(dòng)干預(yù)
? 集群(直連型)
從redis 3.0之后版本支持redis-cluster集群棍鳖,Redis-Cluster采用無中心結(jié)構(gòu)职车,每個(gè)節(jié)點(diǎn)保存數(shù)據(jù)和整個(gè)集群狀態(tài),每個(gè)節(jié)點(diǎn)都和其他所有節(jié)點(diǎn)連接。
特點(diǎn):
1鹊杖、無中心架構(gòu)(不存在哪個(gè)節(jié)點(diǎn)影響性能瓶頸),少了 proxy 層扛芽。
2骂蓖、數(shù)據(jù)按照 slot 存儲(chǔ)分布在多個(gè)節(jié)點(diǎn),節(jié)點(diǎn)間數(shù)據(jù)共享川尖,可動(dòng)態(tài)調(diào)整數(shù)據(jù)分布登下。
3、可擴(kuò)展性叮喳,可線性擴(kuò)展到 1000 個(gè)節(jié)點(diǎn)被芳,節(jié)點(diǎn)可動(dòng)態(tài)添加或刪除。
4馍悟、高可用性畔濒,部分節(jié)點(diǎn)不可用時(shí),集群仍可用锣咒。通過增加 Slave 做備份數(shù)據(jù)副本
5侵状、實(shí)現(xiàn)故障自動(dòng) failover,節(jié)點(diǎn)之間通過 gossip 協(xié)議交換狀態(tài)信息毅整,用投票機(jī)制完成 Slave到 Master 的角色提升趣兄。
缺點(diǎn):
1、資源隔離性較差悼嫉,容易出現(xiàn)相互影響的情況艇潭。
2、數(shù)據(jù)通過異步復(fù)制,不保證數(shù)據(jù)的強(qiáng)一致性
6戏蔑、Redis AOF文件過大蹋凝?AOF重寫的作用?
隨著命令不斷的寫入數(shù)據(jù)辛臊,AOF文件會(huì)越來越大仙粱。為了解決這個(gè)問題,redis 引入了 AOF文件重寫機(jī)制彻舰,以便壓縮 AOF體積 伐割,更小的 AOF文件可以更快的被redis加載
從 Redis 2.4開始候味, AOF重寫由 Redis自行觸發(fā), 可以使用BGREWRITEAOF手動(dòng)觸發(fā)重寫操作
? AOF重寫的作用
減少磁盤占用量 隔心、加速恢復(fù)速度
7白群、Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)
? 簡(jiǎn)單動(dòng)態(tài)字符串 simple dynamic string,SDS
? 鏈表
? 字典 又稱為符號(hào)表或者關(guān)聯(lián)數(shù)組、或映射(map)
? 跳躍表 skiplist
? 整數(shù)集合 intset
? 壓縮列表 ziplist
8硬霍、Redis過期key處理策略
Redis中有個(gè)設(shè)置時(shí)間過期的功能帜慢,即對(duì)存儲(chǔ)在 redis 數(shù)據(jù)庫中的值可以設(shè)置一個(gè)過期時(shí)間。作為一個(gè)緩存數(shù)據(jù)庫唯卖,這是非常實(shí)用的粱玲。如項(xiàng)目中的 token 或者一些登錄信息,尤其是短信驗(yàn)證碼都是有時(shí)間限制的拜轨,按照傳統(tǒng)的數(shù)據(jù)庫處理方式抽减,一般都是自己判斷過期,這樣無疑會(huì)嚴(yán)重影響項(xiàng)目性能橄碾。
操作set key 的時(shí)候卵沉,都可以給一個(gè) expire time,就是過期時(shí)間法牲,通過過期時(shí)間可以指定這個(gè) key可以存活的時(shí)間史汗。
如果假設(shè)你設(shè)置了一批 key 只能存活1個(gè)小時(shí),那么接下來1小時(shí)后拒垃,redis是怎么對(duì)這批key進(jìn)行刪除的停撞?
定期刪除 + 惰性刪除 ? ?通過名字大概就能猜出這兩個(gè)刪除方式的意思了。
? 定期刪除:redis默認(rèn)是每隔 100ms 就隨機(jī)抽取一些設(shè)置了過期時(shí)間的key悼瓮,檢查其是否過期怜森,如果過期就刪除。注意這里是隨機(jī)抽取的谤牡。為什么要隨機(jī)呢副硅?你想一想假如 redis 存了幾十萬個(gè) key ,每隔100ms就遍歷所有的設(shè)置過期時(shí)間的 key 的話翅萤,就會(huì)給 CPU 帶來很大的負(fù)載恐疲!
? 惰性刪除 :定期刪除可能會(huì)導(dǎo)致很多過期 key 到了時(shí)間并沒有被刪除掉。所以就有了惰性刪除套么。假如你的過期 key培己,靠定期刪除沒有被刪除掉,還停留在內(nèi)存里胚泌,除非你的系統(tǒng)去查一下那個(gè) key省咨,才會(huì)被redis給刪除掉。這就是所謂的惰性刪除玷室,也是夠懶的哈零蓉!
僅僅通過設(shè)置過期時(shí)間還是有問題的笤受。想一下:如果定期刪除漏掉了很多過期 key,然后也沒及時(shí)去查敌蜂,也就沒走惰性刪除箩兽,此時(shí)會(huì)怎么樣?如果大量過期key堆積在內(nèi)存里章喉,導(dǎo)致redis內(nèi)存塊耗盡了汗贫。怎么解決這個(gè)問題呢?
9秸脱、Redis事務(wù)
Redis通過 MULTI落包、EXEC、WATCH等命令來實(shí)現(xiàn)事務(wù)(transaction)功能摊唇。事務(wù)提供了一種將多個(gè)命令請(qǐng)求打包妥色,然后一次性、按順序地執(zhí)行多個(gè)命令的機(jī)制遏片,并且在事務(wù)執(zhí)行期間,服務(wù)器不會(huì)中斷事務(wù)而改去執(zhí)行其他客戶端的命令請(qǐng)求撮竿,它會(huì)將事務(wù)中的所有命令都執(zhí)行完畢吮便,然后才去處理其他客戶端的命令請(qǐng)求。
在傳統(tǒng)的關(guān)系式數(shù)據(jù)庫中幢踏,常常用ACID性質(zhì)來檢驗(yàn)事務(wù)功能的可靠性和安全性髓需。在 Redis中,事務(wù)總是具有原子性(Atomicity)房蝉、一致性(Consistency)和隔離性(Isolation)僚匆,并且當(dāng) Redis 運(yùn)行在某種特定的持久化模式下時(shí),事務(wù)也具有持久性(Durability)搭幻。
10咧擂、如何保證緩存與數(shù)據(jù)庫雙寫時(shí)的數(shù)據(jù)一致性
如果不是嚴(yán)格要求“緩存和數(shù)據(jù)庫”必須保證一致性的話,最好不要做這個(gè)方案:即 讀請(qǐng)求和寫請(qǐng)求串行化檀蹋,串到一個(gè)內(nèi)存隊(duì)列里面去松申。串行化可以保證一定不會(huì)出現(xiàn)不一致的情況,但會(huì)導(dǎo)致系統(tǒng)吞吐量大幅度降低俯逾。
解決這個(gè)問題的最經(jīng)典的模式贸桶,就是Cache Aside Pattern。
Cache Aside Pattern:
? 讀的時(shí)候先讀緩存桌肴,如果緩存不存在的話就讀數(shù)據(jù)庫皇筛,取出數(shù)據(jù)庫后更新緩存;如果存在的話直接讀取緩存的信息坠七。
? 寫的時(shí)候水醋,先更新數(shù)據(jù)庫旗笔,再刪除緩存。
說到這個(gè)問題离例,又會(huì)出現(xiàn)很多問題:
? 為什么是刪除緩存换团,而不是更新緩存?
? 為什么是先更新數(shù)據(jù)庫宫蛆,再刪除緩存艘包?不是先刪除緩存,再更新數(shù)據(jù)庫耀盗?
寫的時(shí)候?yàn)槭裁词莿h除緩存不是更新緩存想虎?
很多時(shí)候復(fù)雜的緩存場(chǎng)景,緩存不是僅僅從數(shù)據(jù)庫中取出來的值叛拷∩喑可能是關(guān)聯(lián)多張表的數(shù)據(jù)并通過計(jì)算才是緩存需要的值。并且忿薇,更新緩存的代價(jià)有時(shí)候很高裙椭。對(duì)于需要頻繁寫操作,而讀操作很少的時(shí)候署浩,每次進(jìn)行數(shù)據(jù)庫的修改揉燃,緩存也要隨之更新,會(huì)造成系統(tǒng)吞吐的下降筋栋,但此時(shí)緩存并不會(huì)被頻繁訪問到炊汤,用到的緩存才去算緩存。
刪除緩存而不是更新緩存弊攘,是一種懶加載的思想抢腐,不是每次都重復(fù)更新緩存,只有用到的時(shí)候才去更新緩存襟交,同時(shí)即使有大量的讀請(qǐng)求迈倍,實(shí)際也就更新了一次,后面的請(qǐng)求不會(huì)重復(fù)讀捣域。
Cache Aside Pattern存在的問題
問題:先更新數(shù)據(jù)庫授瘦,再刪除緩存,如果更新緩存失敗了竟宋,導(dǎo)致數(shù)據(jù)庫中是新數(shù)據(jù)提完,緩存中是舊數(shù)據(jù),就出現(xiàn)數(shù)據(jù)不一致的問題丘侠。
解決思路:先刪除緩存徒欣,再更新數(shù)據(jù)庫。
緩存刪除失斘献帧:如果緩存刪除失敗打肝,那么數(shù)據(jù)庫信息沒有被修改脂新,保持了數(shù)據(jù)的一致性;
緩存刪除成功粗梭,數(shù)據(jù)庫更新失斦恪:此時(shí)數(shù)據(jù)庫里的是舊數(shù)據(jù),緩存是空的断医,查詢時(shí)發(fā)現(xiàn)緩存不存在滞乙,就查詢數(shù)據(jù)庫并更新緩存,數(shù)據(jù)保持一致鉴嗤。問題:上面的方案存在不足斩启,如果刪除完緩存更新數(shù)據(jù)庫時(shí),如果一個(gè)請(qǐng)求過來查詢數(shù)據(jù)醉锅,緩存不存在兔簇,就查詢數(shù)據(jù)庫的舊數(shù)據(jù),更新舊數(shù)據(jù)到緩存中硬耍。隨后數(shù)據(jù)更新完成垄琐,修改了數(shù)據(jù)庫的數(shù)據(jù),此時(shí)緩存和數(shù)據(jù)庫的數(shù)據(jù)就會(huì)出現(xiàn)不一致了经柴。高并發(fā)下會(huì)出現(xiàn)這種數(shù)據(jù)庫+緩存不一致的情況狸窘。如果不采用給緩存設(shè)置過期時(shí)間策略,該數(shù)據(jù)永遠(yuǎn)都是臟數(shù)據(jù)口锭。
解決方案:采用雙刪除策略。寫請(qǐng)求先刪除緩存介杆,再去更新數(shù)據(jù)庫鹃操,等待一段時(shí)間后異步刪除緩存。這樣可以保證在讀取錯(cuò)誤數(shù)據(jù)時(shí)能及時(shí)被修正過來春哨。
還有一種策略荆隘,就是:寫請(qǐng)求先修改緩存為指定值,然后再去更新數(shù)據(jù)庫赴背,再更新緩存椰拒。讀請(qǐng)求過來后,會(huì)先讀緩存凰荚,判斷是指定值后就進(jìn)入循環(huán)讀取狀態(tài)燃观,等到寫請(qǐng)求更新緩存。如果循環(huán)超時(shí)就去數(shù)據(jù)庫讀取數(shù)據(jù)便瑟,更新緩存缆毁。
這種方案保證了讀寫的一致性,但由于讀請(qǐng)求等待寫請(qǐng)求的完成到涂,會(huì)降低系統(tǒng)的吞吐量脊框。
11颁督、何解決Redis的并發(fā)競(jìng)爭(zhēng)Key問題
所謂Redis的并發(fā)競(jìng)爭(zhēng)Key的問題也就是多個(gè)系統(tǒng)同時(shí)對(duì)一個(gè)key進(jìn)行操作,但是最后執(zhí)行的順序與期望的順序一致浇雹,這樣也就導(dǎo)致了結(jié)果的不同沉御!
推薦一種方案:分布式鎖(zookeeper和redis都可以實(shí)現(xiàn)分布式鎖)。如果不存在Redis的并發(fā)競(jìng)爭(zhēng)Key問題昭灵,不要使用分布式鎖吠裆,這樣會(huì)影響性能
基于zookeeper臨時(shí)有序節(jié)點(diǎn)可以實(shí)現(xiàn)的分布式鎖。大致思想為:每個(gè)客戶端對(duì)某個(gè)方法加鎖時(shí)虎锚,在zookeeper上的與該方法對(duì)應(yīng)的指定節(jié)點(diǎn)的目錄下硫痰,生成一個(gè)唯一的瞬時(shí)有序節(jié)點(diǎn)。判斷是否獲取鎖的方式很簡(jiǎn)單窜护,只需要判斷有序節(jié)點(diǎn)中序號(hào)最小的一個(gè)效斑。當(dāng)釋放鎖的時(shí)候,只需將這個(gè)瞬時(shí)節(jié)點(diǎn)刪除即可柱徙。同時(shí)缓屠,其可以避免服務(wù)宕機(jī)導(dǎo)致的鎖無法釋放,而產(chǎn)生的死鎖問題护侮。完成業(yè)務(wù)流程后敌完,刪除對(duì)應(yīng)的子節(jié)點(diǎn)釋放鎖。
在實(shí)踐中羊初,當(dāng)然是從以可靠性為主; 所以首推Zookeeper滨溉。
12、Redis分布式鎖的注意事項(xiàng)
互斥性长赞。在任意時(shí)刻晦攒,只有一個(gè)客戶端能持有鎖。
不會(huì)發(fā)生死鎖得哆。即使有一個(gè)客戶端在持有鎖的期間崩潰而沒有主動(dòng)解鎖脯颜,也能保證后續(xù)其他客戶端能加鎖。
具有容錯(cuò)性贩据。只要大部分的Redis節(jié)點(diǎn)正常運(yùn)行栋操,客戶端就可以加鎖和解鎖。
解鈴還須系鈴人饱亮。加鎖和解鎖必須是同一個(gè)客戶端矾芙,客戶端自己不能把別人加的鎖給解了。
業(yè)務(wù)執(zhí)行時(shí)間超過鎖的有效期時(shí)近上,如何有效進(jìn)行延遲鎖的有效期蠕啄。添加一個(gè)看門狗線程,進(jìn)行鎖有效期檢測(cè)
13、假如Redis里面有1億個(gè)key歼跟,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開頭的和媳,如果將它們?nèi)空页? 來?
使用keys指令可以掃出指定模式的key列表:keys pre*
14哈街、如果這個(gè)redis正在給線上的業(yè)務(wù)提供服務(wù)留瞳,那使用keys指令會(huì)有什么問題?
這個(gè)時(shí)候你要回答redis關(guān)鍵的一個(gè)特性:redis的單線程的骚秦。keys指令會(huì)導(dǎo)致線程阻塞一段時(shí)間她倘,線上服務(wù)會(huì)停頓,直到指令執(zhí)行完畢作箍,服務(wù)才能恢復(fù)硬梁。
這個(gè)時(shí)候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key列表胞得,但是會(huì)有一定的重復(fù)概率荧止,在客戶端做一次去重就可以了,但是整體所花費(fèi)的時(shí)間會(huì)比直接用keys指令長阶剑。
15跃巡、 使用過Redis做異步隊(duì)列么,你是怎么用的牧愁?
一般使用list結(jié)構(gòu)作為隊(duì)列素邪,rpush生產(chǎn)消息,lpop消費(fèi)消息猪半。當(dāng)lpop沒有消息的時(shí)候兔朦,要適當(dāng)sleep一會(huì)再重試。
如果對(duì)方追問可不可以不用sleep呢磨确?list還有個(gè)指令叫blpop沽甥,在沒有消息的時(shí)候,它會(huì)阻塞住直到消息到來俐填。
如果對(duì)方追問能不能生產(chǎn)一次消費(fèi)多次呢安接?使用pub/sub主題訂閱者模式翔忽,可以實(shí)現(xiàn)1:N的消息隊(duì)列英融。
如果對(duì)方追問pub/sub有什么缺點(diǎn)?在消費(fèi)者下線的情況下歇式,生產(chǎn)的消息會(huì)丟失驶悟,得使用專業(yè)的消息隊(duì)列如rabbitmq等。redis中pub/sub缺陷
16材失、如果對(duì)方追問redis如何實(shí)現(xiàn)延時(shí)隊(duì)列痕鳍?
使用有序集合,拿時(shí)間戳作為score,消息內(nèi)容作為key調(diào)用zadd來生產(chǎn)消息笼呆,消費(fèi)者用zrangebyscore指令獲取N秒之前的數(shù)據(jù)輪詢進(jìn)行處理熊响。
66、如果有大量的key需要設(shè)置同一時(shí)間過期诗赌,一般需要注意什么
如果大量的key過期時(shí)間設(shè)置的過于集中汗茄,到過期的那個(gè)時(shí)間點(diǎn),redis可能會(huì)出現(xiàn)短暫的卡頓現(xiàn)象铭若。一般需要在時(shí)間上加一個(gè)隨機(jī)值洪碳,使得過期時(shí)間分散一些。
17叼屠、 Redis如何做持久化的瞳腌?
? RDB做鏡像全量持久化,AOF做增量持久化镜雨。
RDB持久化也分兩種:SAVE和BGSAVE嫂侍。
SAVE是阻塞式的RDB持久化,當(dāng)執(zhí)行這個(gè)命令時(shí)redis的主進(jìn)程把內(nèi)存里的數(shù)據(jù)庫狀態(tài)寫入到RDB文件中冷离,直到該文件創(chuàng)建完畢的這段時(shí)間內(nèi)redis將不能處理任何命令請(qǐng)求吵冒;1 BGSAVE屬于非阻塞式的持久化,它會(huì)創(chuàng)建一個(gè)子進(jìn)程專門去把內(nèi)存中的數(shù)據(jù)庫狀態(tài)寫入RDB文件里西剥,同時(shí)主進(jìn)程還可以處理來自客戶端的命令請(qǐng)求痹栖。
但子進(jìn)程基本是復(fù)制的父進(jìn)程,這等于兩個(gè)相同大小的redis進(jìn)程在系統(tǒng)上運(yùn)行瞭空,會(huì)造成內(nèi)存使用率的大幅增加揪阿。
? AOF的持久化是通過命令追加、文件寫入和文件同步三個(gè)步驟實(shí)現(xiàn)的咆畏。
當(dāng)reids開啟AOF后(redis備份方式默認(rèn)是RDB);
服務(wù)端每執(zhí)行一次寫操作(如set南捂、sadd、rpush)就會(huì)把該條命令追加到一個(gè)單獨(dú)的AOF緩沖區(qū)的末尾旧找,這就是命令追加溺健;
然后把AOF緩沖區(qū)的內(nèi)容寫入AOF文件里∨ブ耄看上去第二步就已經(jīng)完成AOF持久化了那第三步是干什么的呢鞭缭?這就需要從系統(tǒng)的文件寫入機(jī)制說起:一般我們現(xiàn)在所使用的操作系統(tǒng),為了提高文件的寫入效率魏颓,都會(huì)有一個(gè)寫入策略岭辣,即當(dāng)你往
硬盤寫入數(shù)據(jù)時(shí),操作系統(tǒng)不是實(shí)時(shí)的將數(shù)據(jù)寫入硬盤甸饱,而是先把數(shù)據(jù)暫時(shí)的保存在一個(gè)內(nèi)存緩沖區(qū)里念颈,等到這個(gè)內(nèi)存緩沖區(qū)的空間被填滿或者是超過了設(shè)定的時(shí)限后才會(huì)真正的把緩沖區(qū)內(nèi)的數(shù)據(jù)寫入硬盤中。也就是說當(dāng)redis進(jìn)行到第二
步文件寫入的時(shí)候涯捻,從用戶的角度看是已經(jīng)把AOF緩沖區(qū)里的數(shù)據(jù)寫入到AOF文件了皇忿,但對(duì)系統(tǒng)而言只不過是把AOF緩沖區(qū)的內(nèi)容放到了另一個(gè)內(nèi)存緩沖區(qū)里而已,之后redis還需要進(jìn)行文件同步把該內(nèi)存緩沖區(qū)里的數(shù)據(jù)真正寫入硬盤上
才算是完成了一次持久化。而何時(shí)進(jìn)行文件同步則是根據(jù)配置的appendfsync來進(jìn)行:appendfsync有三個(gè)選項(xiàng):always、everysec和no:
18、Pipeline有什么好處矗烛,為什么要用pipeline?
可以將多次IO往返的時(shí)間縮減為一次箩溃,前提是pipeline執(zhí)行的指令之間沒有因果相關(guān)性瞭吃。使用redis-benchmark進(jìn)行壓測(cè)的時(shí)候可以發(fā)現(xiàn)影響redis的QPS峰值的一個(gè)重要因素是pipeline批次指令的數(shù)目。
19涣旨、Redis的同步機(jī)制了解么歪架?
Redis可以使用主從同步,從從同步霹陡。第一次同步時(shí)和蚪,主節(jié)點(diǎn)做一次bgsave,并同時(shí)將后續(xù)修改操作記錄到內(nèi)存buffer烹棉,待完成后將rdb文件全量同步到復(fù)制節(jié)點(diǎn)攒霹,復(fù)制節(jié)點(diǎn)接受完成后將rdb鏡像加載到內(nèi)存。
加載完成后浆洗,再通知主節(jié)點(diǎn)將期間修改的操作記錄同步到復(fù)制節(jié)點(diǎn)進(jìn)行重放就完成了同步過程催束。
20、是否使用過Redis集群伏社,集群的原理是什么抠刺?
Redis Sentinal著眼于高可用,在master宕機(jī)時(shí)會(huì)自動(dòng)將slave提升為master摘昌,繼續(xù)提供服務(wù)速妖。
Redis Cluster著眼于擴(kuò)展性,在單個(gè)redis內(nèi)存不足時(shí)聪黎,使用Cluster進(jìn)行分片存儲(chǔ)罕容。
21、使用redis有哪些好處稿饰?
? 速度快锦秒,因?yàn)閿?shù)據(jù)存在內(nèi)存中,類似于HashMap湘纵,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1)
? 支持豐富數(shù)據(jù)類型脂崔,支持string滤淳,list梧喷,set,sorted set,hash
? 支持事務(wù)铺敌,操作都是原子性汇歹,所謂的原子性就是對(duì)數(shù)據(jù)的更改要么全部執(zhí)行,要么全部不執(zhí)行
? 豐富的特性:可用于緩存偿凭,消息产弹,按key設(shè)置過期時(shí)間,過期后將會(huì)自動(dòng)刪除
22弯囊、redis相比memcached有哪些優(yōu)勢(shì)痰哨?Memcache與Redis的區(qū)別都有哪些?
? 優(yōu)勢(shì)
memcached所有的值均是簡(jiǎn)單的字符串匾嘱,redis作為其替代者斤斧,支持更為豐富的數(shù)據(jù)類型
redis的速度比memcached快很多
redis可以持久化其數(shù)據(jù)
? 區(qū)別
存儲(chǔ)方式 Memecache把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會(huì)掛掉霎烙,數(shù)據(jù)不能超過內(nèi)存大小撬讽。Redis有部份存在硬盤上,這樣能保證數(shù)據(jù)的持久性悬垃。
數(shù)據(jù)支持類型 Memcache對(duì)數(shù)據(jù)類型支持相對(duì)簡(jiǎn)單游昼。Redis有復(fù)雜的數(shù)據(jù)類型。
使用底層模型不同 它們之間底層實(shí)現(xiàn)方式 以及與客戶端之間通信的應(yīng)用協(xié)議不一樣尝蠕。Redis直接自己構(gòu)建了VM 機(jī)制 烘豌,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會(huì)浪費(fèi)一定的時(shí)間去移動(dòng)和請(qǐng)求看彼。
23扇谣、redis常見性能問題和解決方案:
Master寫內(nèi)存快照,save命令調(diào)度rdbSave函數(shù)闲昭,會(huì)阻塞主線程的工作罐寨,當(dāng)快照比較大時(shí)對(duì)性能影響是非常大的,會(huì)間斷性暫停服務(wù)序矩,所以Master最好不要寫內(nèi)存快照鸯绿。
Master AOF持久化,如果不重寫AOF文件簸淀,這個(gè)持久化方式對(duì)性能的影響是最小的瓶蝴,但是AOF文件會(huì)不斷增大,AOF文件過大會(huì)影響Master重啟的恢復(fù)速度租幕。
Master最好不要做任何持久化工作舷手,包括內(nèi)存快照和AOF日志文件,特別是不要啟用內(nèi)存快照做持久化,如果數(shù)據(jù)比較關(guān)鍵劲绪,某個(gè)Slave開啟AOF備份數(shù)據(jù)男窟,策略為每秒同步一次盆赤。
Master調(diào)用BGREWRITEAOF重寫AOF文件,AOF在重寫的時(shí)候會(huì)占大量的CPU和內(nèi)存資源歉眷,導(dǎo)致服務(wù)load過高牺六,出現(xiàn)短暫服務(wù)暫停現(xiàn)象汗捡。
Redis主從復(fù)制的性能問題淑际,為了主從復(fù)制的速度和連接的穩(wěn)定性,Slave和Master最好在同一個(gè)局域網(wǎng)內(nèi)
24扇住、為什么redis需要把所有數(shù)據(jù)放到內(nèi)存中?
Redis為了達(dá)到最快的讀寫速度將數(shù)據(jù)都讀到內(nèi)存中春缕,并通過異步的方式將數(shù)據(jù)寫入磁盤。所以redis具有快速和數(shù)據(jù)持久化的特征艘蹋。如果不將數(shù)據(jù)放在內(nèi)存中淡溯,磁盤I/O速度為嚴(yán)重影響redis的性能。
在內(nèi)存越來越便宜的今天簿训,redis將會(huì)越來越受歡迎咱娶。如果設(shè)置了最大使用的內(nèi)存,則數(shù)據(jù)已有記錄數(shù)達(dá)到內(nèi)存限值后不能繼續(xù)插入新值强品。
25膘侮、Redis是單進(jìn)程單線程的
redis利用隊(duì)列技術(shù)將并發(fā)訪問變?yōu)榇性L問,消除了傳統(tǒng)數(shù)據(jù)庫串行控制的開銷的榛。
26琼了、redis的并發(fā)競(jìng)爭(zhēng)問題如何解決?
Redis為單進(jìn)程單線程模式,采用隊(duì)列模式將并發(fā)訪問變?yōu)榇性L問夫晌。Redis本身沒有鎖的概念雕薪,Redis對(duì)于多個(gè)客戶端連接并不存在競(jìng)爭(zhēng),但是在Jedis客戶端對(duì)Redis進(jìn)行并發(fā)訪問時(shí)會(huì)發(fā)生連接超時(shí)晓淀、數(shù)據(jù)轉(zhuǎn)換錯(cuò)誤所袁、阻塞、客戶端關(guān)閉連接等問題凶掰,這些問題均是由于客戶端連接混亂造成燥爷。對(duì)此有2種解決方法:
? 客戶端角度,為保證每個(gè)客戶端間正常有序與Redis進(jìn)行通信懦窘,對(duì)連接進(jìn)行池化前翎,同時(shí)對(duì)客戶端讀寫Redis操作采用內(nèi)部鎖synchronized。
+服務(wù)器角度畅涂,利用setnx實(shí)現(xiàn)鎖港华。
注:對(duì)于第一種,需要應(yīng)用程序自己處理資源的同步午衰,可以使用的方法比較通俗立宜,可以使用synchronized也可以使用lock冒萄;第二種需要用到Redis的setnx命令,但是需要注意一些問題赘理。
27、redis事物的了解CAS(check-and-set 操作實(shí)現(xiàn)樂觀鎖 )?
和眾多其它數(shù)據(jù)庫一樣扇单,Redis作為NoSQL數(shù)據(jù)庫也同樣提供了事務(wù)機(jī)制商模。在Redis中,MULTI/EXEC/DISCARD/WATCH這四個(gè)命令是我們實(shí)現(xiàn)事務(wù)的基石蜘澜。相信對(duì)有關(guān)系型數(shù)據(jù)庫開發(fā)經(jīng)驗(yàn)的開發(fā)者而言這一概念并不陌生施流,即便如此,我們還是會(huì)簡(jiǎn)要的列出Redis中事務(wù)的實(shí)現(xiàn)特征:
? 在事務(wù)中的所有命令都將會(huì)被串行化的順序執(zhí)行鄙信,事務(wù)執(zhí)行期間瞪醋,Redis不會(huì)再為其它客戶端的請(qǐng)求提供任何服務(wù),從而保證了事物中的所有命令被原子的執(zhí)行装诡。
? 和關(guān)系型數(shù)據(jù)庫中的事務(wù)相比银受,在Redis事務(wù)中如果有某一條命令執(zhí)行失敗,其后的命令仍然會(huì)被繼續(xù)執(zhí)行鸦采。
? 可以通過MULTI命令開啟一個(gè)事務(wù)宾巍,有關(guān)系型數(shù)據(jù)庫開發(fā)經(jīng)驗(yàn)的人可以將其理解為"BEGIN TRANSACTION"語句。在該語句之后執(zhí)行的命令都將被視為事務(wù)之內(nèi)的操作渔伯,最后我們可以通過執(zhí)行
EXEC/DISCARD命令來提交/回滾該事務(wù)內(nèi)的所有操作顶霞。這兩個(gè)Redis命令可被視為等同于關(guān)系型數(shù)據(jù)庫中的COMMIT/ROLLBACK語句。
? 在事務(wù)開啟之前锣吼,如果客戶端與服務(wù)器之間出現(xiàn)通訊故障并導(dǎo)致網(wǎng)絡(luò)斷開选浑,其后所有待執(zhí)行的語句都將不會(huì)被服務(wù)器執(zhí)行。然而如果網(wǎng)絡(luò)中斷事件是發(fā)生在客戶端執(zhí)行EXEC命令之后玄叠,那么該事務(wù)中的所有命令都會(huì)被服務(wù)器執(zhí)行古徒。
? 當(dāng)使用Append-Only模式時(shí),Redis會(huì)通過調(diào)用系統(tǒng)函數(shù)write將該事務(wù)內(nèi)的所有寫操作在本次調(diào)用中全部寫入磁盤读恃。然而如果在寫入的過程中出現(xiàn)系統(tǒng)崩潰描函,如電源故障導(dǎo)致的宕機(jī),那么此時(shí)也許只有部分?jǐn)?shù)據(jù)被寫入到磁盤狐粱,
而另外一部分?jǐn)?shù)據(jù)卻已經(jīng)丟失舀寓。Redis服務(wù)器會(huì)在重新啟動(dòng)時(shí)執(zhí)行一系列必要的一致性檢測(cè),一旦發(fā)現(xiàn)類似問題肌蜻,就會(huì)立即退出并給出相應(yīng)的錯(cuò)誤提示互墓。此時(shí),我們就要充分利用Redis工具包中提供的redis-check-aof工具蒋搜,
該工具可以幫助我們定位到數(shù)據(jù)不一致的錯(cuò)誤篡撵,并將已經(jīng)寫入的部分?jǐn)?shù)據(jù)進(jìn)行回滾判莉。修復(fù)之后我們就可以再次重新啟動(dòng)Redis服務(wù)器了。
28育谬、 redis持久化的幾種方式
? 快照(snapshots)
缺省情況情況下券盅,Redis把數(shù)據(jù)快照存放在磁盤上的二進(jìn)制文件中,文件名為dump.rdb膛檀。你可以配置Redis的持久化策略锰镀,例如數(shù)據(jù)集中每N秒鐘有超過M次更新,就將數(shù)據(jù)寫入磁盤咖刃;或者你可以手工調(diào)用命令SAVE或BGSAVE泳炉。
工作原理:Redis forks. 子進(jìn)程開始將數(shù)據(jù)寫到臨時(shí)RDB文件中。當(dāng)子進(jìn)程完成寫RDB文件嚎杨,用新文件替換老文件花鹅。這種方式可以使Redis使用copy-on-write技術(shù)。
? AOF
快照模式并不健壯枫浙,當(dāng)系統(tǒng)停止刨肃,或者無意中Redis被kill掉,最后寫入Redis的數(shù)據(jù)就會(huì)丟失箩帚。這對(duì)某些應(yīng)用也許不是大問題之景,但對(duì)于要求高可靠性的應(yīng)用來說,Redis就不是一個(gè)合適的選擇膏潮。Append-only文件模式是另一種選擇锻狗。你可以在配置文件中打開AOF模式。
? 虛擬內(nèi)存方式
當(dāng)你的key很小而value很大時(shí),使用VM的效果會(huì)比較好.因?yàn)檫@樣節(jié)約的內(nèi)存比較大. 當(dāng)你的key不小時(shí),可以考慮使用一些非常方法將很大的key變成很大的value,比如你可以考慮將key,value組合成一個(gè)新的value. vm-max-threads這個(gè)參數(shù),可以設(shè)置訪問swap文件的線程數(shù),設(shè)置最好不要超過機(jī)器的核數(shù),如果設(shè)置為0,那么所有對(duì)swap文件的操作都是串行的.可能會(huì)造成比較長時(shí)間的延遲,但是對(duì)數(shù)據(jù)完整性有很好的保證.