1.什么是 Redis舔涎?簡(jiǎn)述它的優(yōu)缺點(diǎn)?
Redis的全稱(chēng)是:Remote Dictionary.Server
篙议,本質(zhì)上是一個(gè)Key-Value
類(lèi)型的內(nèi)存數(shù)據(jù)庫(kù)恶导,很像memcached
,整個(gè)數(shù)據(jù)庫(kù)統(tǒng)統(tǒng)加載在內(nèi)存當(dāng)中進(jìn)行操作挪哄,定期通過(guò)異步操作把數(shù)據(jù)庫(kù)數(shù)據(jù)flush
到硬盤(pán)上進(jìn)行保存吧秕。因?yàn)槭羌儍?nèi)存操作,Redis
的性能非常出色中燥,每秒可以處理超過(guò) 10 萬(wàn)次讀寫(xiě)操作寇甸,是已知性能最快的Key-Value DB。
Redis 的出色之處不僅僅是性能疗涉,Redis
最大的魅力是支持保存多種數(shù)據(jù)結(jié)構(gòu)拿霉,此外單個(gè) value
的最大限制是 1GB
,不像 memcached 只能保存 1MB 的數(shù)據(jù)咱扣,因此 Redis 可以用來(lái)實(shí)現(xiàn)很多有用的功能绽淘。
比方說(shuō)用他的 List
來(lái)做 FIFO
雙向鏈表,實(shí)現(xiàn)一個(gè)輕量級(jí)的高性 能消息隊(duì)列服務(wù)闹伪,用他的 Set
可以做高性能的 tag
系統(tǒng)等等沪铭。
另外 Redis
也可以對(duì)存入的 Key-Value
設(shè)置 expire
時(shí)間,因此也可以被當(dāng)作一個(gè)功能加強(qiáng)版的memcached 來(lái)用偏瓤。 Redis 的主要缺點(diǎn)是數(shù)據(jù)庫(kù)容量受到物理內(nèi)存的限制杀怠,不能用作海量數(shù)據(jù)的高性能讀寫(xiě),因此 Redis 適合的場(chǎng)景主要局限在較小數(shù)據(jù)量的高性能操作和運(yùn)算上厅克。
2.Redis 支持的 Java 客戶端都有哪些赔退?官方推薦用哪個(gè)?
Redisson证舟、Jedis硕旗、lettuce 等等,官方推薦使用 Redisson
女责。
3.Redis 與 Memcached 相比有哪些優(yōu)勢(shì)漆枚?
-
memcached
所有的值均是簡(jiǎn)單的字符串,redis
作為其替代者抵知,支持更為豐富的數(shù)據(jù)類(lèi)型墙基。 -
redis
的速度比memcached
快很多。 -
redis
可以持久化其數(shù)據(jù)刷喜。
Redis 與 Memcached區(qū)別
4.Redis 支持哪幾種數(shù)據(jù)類(lèi)型残制?并簡(jiǎn)單介紹一下?
String(字符串)吱肌、Hash(哈希)痘拆、List(列表)、Set(集合)氮墨、Zset(sorted set:有序集合)
String(字符串)
String是redis最基本的類(lèi)型纺蛆,你可以理解成與Memcached一模一樣的類(lèi)型,一個(gè)key對(duì)應(yīng)一個(gè)value规揪。
String類(lèi)型是二進(jìn)制安全的桥氏。意思是redis的string可以包含任何數(shù)據(jù)。比如jpg圖片或者序列化的對(duì)象 猛铅。
String類(lèi)型是Redis最基本的數(shù)據(jù)類(lèi)型字支,一個(gè)鍵最大能存儲(chǔ)512MB。
一個(gè)鍵能存512M,但是取出來(lái)的時(shí)候就要注意了堕伪。如果存的value過(guò)大揖庄,卻用String接收的話,就會(huì)拋異常了欠雌。我們就出現(xiàn)過(guò)線上問(wèn)題~
Hash(哈希)
Redis hash是一個(gè)鍵值對(duì)集合蹄梢。
Redis hash是一個(gè)string類(lèi)型的field和value的映射表,hash特別適合用于存儲(chǔ)對(duì)象富俄。每個(gè) hash 可以存儲(chǔ) 2^32 - 1鍵值對(duì)(40多億)禁炒。
List(列表)
Redis 列表是簡(jiǎn)單的字符串列表,按照插入順序排序霍比。你可以添加一個(gè)元素導(dǎo)列表的頭部(左邊)或者尾部(右邊)幕袱。
列表最多可存儲(chǔ) 2^32 - 1元素 (4294967295, 每個(gè)列表可存儲(chǔ)40多億)。
Set(集合)
Redis的Set是string類(lèi)型的無(wú)序集合悠瞬。
集合是通過(guò)哈希表實(shí)現(xiàn)的们豌,所以添加,刪除阁危,查找的復(fù)雜度都是O(1)玛痊。
sadd 命令:添加一個(gè)string元素到,key對(duì)應(yīng)的set集合中,成功返回1,如果元素以及在集合中返回0,key對(duì)應(yīng)的set不存在返回錯(cuò)誤狂打。
Zset
Redis
zset
和set
一樣也是string
類(lèi)型元素的集合,且不允許重復(fù)的成員擂煞。不同的是每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè)double
類(lèi)型的分?jǐn)?shù)。redis
正是通過(guò)分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序趴乡。
zset
的成員是唯一的,但分?jǐn)?shù)(score
)卻可以重復(fù)对省。
zadd
命令:添加元素到集合,元素在集合中存在則更新對(duì)應(yīng)score
.
5.怎么理解 Redis 事務(wù)晾捏?相關(guān)事務(wù)命令有哪些蒿涎?并介紹一下
事務(wù)是一個(gè)單獨(dú)的隔離操作:事務(wù)中的所有命令都會(huì)序列化、按順序地執(zhí)行惦辛,事務(wù)在執(zhí)行的過(guò)程中劳秋,不會(huì)被其他客戶端發(fā)送來(lái)的命令請(qǐng)求所打斷。事務(wù)是一個(gè)原子操作:事務(wù)中的命令要么全部被執(zhí)行胖齐,要么全部都不執(zhí)行玻淑。
命令:MULTI
、EXEC
呀伙、DISCARD
补履、WATCH
、UNWATCH
.
- DISCARD
取消事務(wù)剿另,放棄執(zhí)行事務(wù)塊內(nèi)的所有命令箫锤。 - EXEC
執(zhí)行所有事務(wù)塊內(nèi)的命令贬蛙。 - MULTI
標(biāo)記一個(gè)事務(wù)塊的開(kāi)始。 - UNWATCH
取消 WATCH 命令對(duì)所有 key 的監(jiān)視谚攒。 - WATCH key [key ...]
監(jiān)視一個(gè)(或多個(gè)) key 阳准,如果在事務(wù)執(zhí)行之前這個(gè)(或這些) key 被其他命令所改動(dòng),那么事務(wù)將被打斷五鲫。
在傳統(tǒng)的關(guān)系式數(shù)據(jù)庫(kù)中溺职,常常用 ACID
性質(zhì)來(lái)檢驗(yàn)事務(wù)功能的可靠性和安全性岔擂。在 Redis
中位喂,事務(wù)總是具有原子性(Atomicity)、一致性(Consistency)和隔離性(Isolation)乱灵,并且當(dāng) Redis 運(yùn)行在某種特定的持久化模式下時(shí)塑崖,事務(wù)也具有持久性(Durability)。
6.為什么要用 redis 而不用 map/guava 做緩存?
緩存分為本地緩存和分布式緩存痛倚。以 Java
為例规婆,使用自帶的map
或者 guava
實(shí)現(xiàn)的是本地緩存,最主要的特點(diǎn)是輕量以及快速蝉稳,生命周期隨著 jvm
的銷(xiāo)毀而結(jié)束抒蚜,并且在多實(shí)例的情況下,每個(gè)實(shí)例都需要各自保存一份緩存耘戚,緩存不具有一致性嗡髓。
使用 redis
或memcached
之類(lèi)的稱(chēng)為分布式緩存,在多實(shí)例的情況下收津,各實(shí)例共用一份緩存數(shù)據(jù)饿这,緩存具有一致性。缺點(diǎn)是需要保持 redis
或 memcached
服務(wù)的高可用撞秋,整個(gè)程序架構(gòu)上較為復(fù)雜长捧。
7. redis 設(shè)置過(guò)期時(shí)間
Redis中有個(gè)設(shè)置時(shí)間過(guò)期的功能,即對(duì)存儲(chǔ)在 redis 數(shù)據(jù)庫(kù)中的值可以設(shè)置一個(gè)過(guò)期時(shí)間吻贿。作為一個(gè)緩存數(shù)據(jù)庫(kù)串结,這是非常實(shí)用的。如我們一般項(xiàng)目中的 token 或者一些登錄信息舅列,尤其是短信驗(yàn)證碼都是有時(shí)間限制的肌割,按照傳統(tǒng)的數(shù)據(jù)庫(kù)處理方式,一般都是自己判斷過(guò)期剧蹂,這樣無(wú)疑會(huì)嚴(yán)重影響項(xiàng)目性能声功。
我們 set key 的時(shí)候,都可以給一個(gè) expire time宠叼,就是過(guò)期時(shí)間先巴,通過(guò)過(guò)期時(shí)間我們可以指定這個(gè) key 可以存活的時(shí)間其爵。
如果假設(shè)你設(shè)置了一批 key 只能存活1個(gè)小時(shí),那么接下來(lái)1小時(shí)后伸蚯,redis是怎么對(duì)這批key進(jìn)行刪除的摩渺?
定期刪除+惰性刪除。
通過(guò)名字大概就能猜出這兩個(gè)刪除方式的意思了剂邮。
定期刪除:redis默認(rèn)是每隔 100ms 就隨機(jī)抽取一些設(shè)置了過(guò)期時(shí)間的key摇幻,檢查其是否過(guò)期,如果過(guò)期就刪除挥萌。注意這里是隨機(jī)抽取的绰姻。為什么要隨機(jī)呢?你想一想假如 redis 存了幾十萬(wàn)個(gè) key 引瀑,每隔100ms就遍歷所有的設(shè)置過(guò)期時(shí)間的 key 的話狂芋,就會(huì)給 CPU 帶來(lái)很大的負(fù)載!
惰性刪除 :定期刪除可能會(huì)導(dǎo)致很多過(guò)期 key 到了時(shí)間并沒(méi)有被刪除掉憨栽。所以就有了惰性刪除帜矾。假如你的過(guò)期 key,靠定期刪除沒(méi)有被刪除掉屑柔,還停留在內(nèi)存里屡萤,除非你的系統(tǒng)去查一下那個(gè) key,才會(huì)被redis給刪除掉掸宛。這就是所謂的惰性刪除死陆,也是夠懶的哈!
但是僅僅通過(guò)設(shè)置過(guò)期時(shí)間還是有問(wèn)題的旁涤。我們想一下:如果定期刪除漏掉了很多過(guò)期 key翔曲,然后你也沒(méi)及時(shí)去查,也就沒(méi)走惰性刪除劈愚,此時(shí)會(huì)怎么樣瞳遍?如果大量過(guò)期key堆積在內(nèi)存里,導(dǎo)致redis內(nèi)存塊耗盡了菌羽。怎么解決這個(gè)問(wèn)題呢掠械?
8. 說(shuō)一說(shuō)Redis 內(nèi)存淘汰機(jī)制(MySQL里有2000w數(shù)據(jù),Redis中只存20w的數(shù)據(jù)注祖,如何保證Redis中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)猾蒂?)
redis
配置文件 redis.conf
中有相關(guān)注釋?zhuān)蠹铱梢宰孕胁殚喕蛘咄ㄟ^(guò)這個(gè)網(wǎng)址查看:
http://download.redis.io/redis-stable/redis.conf
redis
提供 6種數(shù)據(jù)淘汰策略:
volatile-lru:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
volatile-ttl:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過(guò)期的數(shù)據(jù)淘汰
volatile-random:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰
allkeys-lru:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),在鍵空間中是晨,移除最近最少使用的key(這個(gè)是最常用的).
allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰
no-eviction:禁止驅(qū)逐數(shù)據(jù)肚菠,也就是說(shuō)當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),新寫(xiě)入操作會(huì)報(bào)錯(cuò)罩缴。這個(gè)應(yīng)該沒(méi)人使用吧蚊逢!
9. 如何解決 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問(wèn)題层扶?
所謂 Redis
的并發(fā)競(jìng)爭(zhēng) Key
的問(wèn)題也就是多個(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
問(wèn)題终抽,不要使用分布式鎖戳表,這樣會(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)致的鎖無(wú)法釋放鞭光,而產(chǎn)生的死鎖問(wèn)題吏廉。完成業(yè)務(wù)流程后,刪除對(duì)應(yīng)的子節(jié)點(diǎn)釋放鎖惰许。
在實(shí)踐中席覆,當(dāng)然是從以可靠性為主。所以首推Zookeeper
汹买。
10.Redis 為什么是單線程的佩伤?
官方FAQ表示,因?yàn)镽edis是基于內(nèi)存的操作晦毙,CPU不是Redis的瓶頸生巡,Redis的瓶頸最有可能是機(jī)器內(nèi)存的大小或者網(wǎng)絡(luò)帶寬。既然單線程容易實(shí)現(xiàn)见妒,而且CPU不會(huì)成為瓶頸孤荣,那就順理成章地采用單線程的方案了(畢竟采用多線程會(huì)有很多麻煩!)Redis利用隊(duì)列技術(shù)將并發(fā)訪問(wèn)變?yōu)榇性L問(wèn)
1)絕大部分請(qǐng)求是純粹的內(nèi)存操作(非承氪В快速)
2)采用單線程,避免了不必要的上下文切換和競(jìng)爭(zhēng)條件
3)非阻塞IO優(yōu)點(diǎn):
1.速度快盐股,因?yàn)閿?shù)據(jù)存在內(nèi)存中,類(lèi)似于HashMap耻卡,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1)
- 支持豐富數(shù)據(jù)類(lèi)型疯汁,支持string,list卵酪,set幌蚊,sorted set秸谢,hash
3.支持事務(wù),操作都是原子性霹肝,所謂的原子性就是對(duì)數(shù)據(jù)的更改要么全部執(zhí)行估蹄,要么全部不執(zhí)行 - 豐富的特性:可用于緩存,消息沫换,按key設(shè)置過(guò)期時(shí)間臭蚁,過(guò)期后將會(huì)自動(dòng)刪除如何解決redis的并發(fā)競(jìng)爭(zhēng)key問(wèn)題
同時(shí)有多個(gè)子系統(tǒng)去set一個(gè)key。這個(gè)時(shí)候要注意什么呢讯赏? 不推薦使用redis的事務(wù)機(jī)制垮兑。因?yàn)槲覀兊纳a(chǎn)環(huán)境,基本都是redis集群環(huán)境漱挎,做了數(shù)據(jù)分片操作系枪。你一個(gè)事務(wù)中有涉及到多個(gè)key操作的時(shí)候,這多個(gè)key不一定都存儲(chǔ)在同一個(gè)redis-server上磕谅。因此私爷,redis的事務(wù)機(jī)制,十分雞肋膊夹。
(1)如果對(duì)這個(gè)key操作衬浑,不要求順序: 準(zhǔn)備一個(gè)分布式鎖,大家去搶鎖放刨,搶到鎖就做set操作即可
(2)如果對(duì)這個(gè)key操作工秩,要求順序: 分布式鎖+時(shí)間戳。 假設(shè)這會(huì)系統(tǒng)B先搶到鎖进统,將key1設(shè)置為{valueB 3:05}助币。接下來(lái)系統(tǒng)A搶到鎖,發(fā)現(xiàn)自己的valueA的時(shí)間戳早于緩存中的時(shí)間戳螟碎,那就不做set操作了眉菱。以此類(lèi)推。
(3) 利用隊(duì)列抚芦,將set方法變成串行訪問(wèn)也可以redis遇到高并發(fā)倍谜,如果保證讀寫(xiě)key的一致性
對(duì)redis的操作都是具有原子性的,是線程安全的操作,你不用考慮并發(fā)問(wèn)題,redis內(nèi)部已經(jīng)幫你處理好并發(fā)的問(wèn)題了。
11.說(shuō)一說(shuō)Redis 持久化機(jī)制叉抡?
Redis
是一個(gè)支持持久化的內(nèi)存數(shù)據(jù)庫(kù)尔崔,通過(guò)持久化機(jī)制把內(nèi)存中的數(shù)據(jù)同步到硬盤(pán)文件來(lái)保證數(shù)據(jù)持久化。當(dāng)Redis
重啟后通過(guò)把硬盤(pán)文件重新加載到內(nèi)存褥民,就能達(dá)到恢復(fù)數(shù)據(jù)的目的季春。
實(shí)現(xiàn):?jiǎn)为?dú)創(chuàng)建fork()
一個(gè)子進(jìn)程,將當(dāng)前父進(jìn)程的數(shù)據(jù)庫(kù)數(shù)據(jù)復(fù)制到子進(jìn)程的內(nèi)存中消返,然后由子進(jìn)程寫(xiě)入到臨時(shí)文件中载弄,持久化的過(guò)程結(jié)束了耘拇,再用這個(gè)臨時(shí)文件替換上次的快照文件,然后子進(jìn)程退出宇攻,內(nèi)存釋放惫叛。
-
RDB是
Redis
默認(rèn)的持久化方式。按照一定的時(shí)間周期策略把內(nèi)存的數(shù)據(jù)以快照的形式保存到硬盤(pán)的二進(jìn)制文件逞刷。即Snapshot快照存儲(chǔ)嘉涌,對(duì)應(yīng)產(chǎn)生的數(shù)據(jù)文件為dump.rdb,通過(guò)配置文件中的save參數(shù)來(lái)定義快照的周期夸浅。( 快照可以是其所表示的數(shù)據(jù)的一個(gè)副本仑最,也可以是數(shù)據(jù)的一個(gè)復(fù)制品。) -
AOF:
Redis
會(huì)將每一個(gè)收到的寫(xiě)命令都通過(guò)Write
函數(shù)追加到文件最后帆喇,類(lèi)似于MySQL
的binlog
警医。當(dāng)Redis
重啟是會(huì)通過(guò)重新執(zhí)行文件中保存的寫(xiě)命令來(lái)在內(nèi)存中重建整個(gè)數(shù)據(jù)庫(kù)的內(nèi)容。
當(dāng)兩種方式同時(shí)開(kāi)啟時(shí)坯钦,數(shù)據(jù)恢復(fù)Redis
會(huì)優(yōu)先選擇AOF
恢復(fù)预皇。
12.熱點(diǎn)數(shù)據(jù)和冷數(shù)據(jù)是什么?
熱點(diǎn)數(shù)據(jù),緩存才有價(jià)值
對(duì)于熱點(diǎn)數(shù)據(jù)葫笼,比如我們的某IM產(chǎn)品深啤,生日祝福模塊,當(dāng)天的壽星列表路星,緩存以后可能讀取數(shù)十萬(wàn)次。再舉個(gè)例子诱桂,某導(dǎo)航產(chǎn)品洋丐,我們將導(dǎo)航信息,緩存以后可能讀取數(shù)百萬(wàn)次挥等。
對(duì)于冷數(shù)據(jù)而言友绝,大部分?jǐn)?shù)據(jù)可能還沒(méi)有再次訪問(wèn)到就已經(jīng)被擠出內(nèi)存,不僅占用內(nèi)存肝劲,而且價(jià)值不大迁客。頻繁修改的數(shù)據(jù),看情況考慮使用緩存
對(duì)于上面兩個(gè)例子辞槐,壽星列表掷漱、導(dǎo)航信息都存在一個(gè)特點(diǎn),就是信息修改頻率不高榄檬,讀取通常非常高的場(chǎng)景卜范。
數(shù)據(jù)更新前至少讀取兩次,緩存才有意義鹿榜。這個(gè)是最基本的策略海雪,如果緩存還沒(méi)有起作用就失效了锦爵,那就沒(méi)有太大價(jià)值了。
那存不存在奥裸,修改頻率很高险掀,但是又不得不考慮緩存的場(chǎng)景呢?有湾宙!比如樟氢,這個(gè)讀取接口對(duì)數(shù)據(jù)庫(kù)的壓力很大,但是又是熱點(diǎn)數(shù)據(jù)创倔,這個(gè)時(shí)候就需要考慮通過(guò)緩存手段嗡害,減少數(shù)據(jù)庫(kù)的壓力,比如我們的某助手產(chǎn)品的畦攘,點(diǎn)贊數(shù)霸妹,收藏?cái)?shù),分享數(shù)等是非常典型的熱點(diǎn)數(shù)據(jù)知押,但是又不斷變化叹螟,此時(shí)就需要將數(shù)據(jù)同步保存到Redis緩存,減少數(shù)據(jù)庫(kù)壓力台盯。
13. 簡(jiǎn)單說(shuō)一說(shuō)緩存雪崩以及解決辦法罢绽?
緩存雪崩我們可以簡(jiǎn)單的理解為:由于原有緩存失效,新緩存未到期間
(例如:我們?cè)O(shè)置緩存時(shí)采用了相同的過(guò)期時(shí)間静盅,在同一時(shí)刻出現(xiàn)大面積的緩存過(guò)期)良价,所有原本應(yīng)該訪問(wèn)緩存的請(qǐng)求都去查詢(xún)數(shù)據(jù)庫(kù)了,而對(duì)數(shù)據(jù)庫(kù)CPU和內(nèi)存造成巨大壓力蒿叠,嚴(yán)重的會(huì)造成數(shù)據(jù)庫(kù)宕機(jī)明垢。從而形成一系列連鎖反應(yīng),造成整個(gè)系統(tǒng)崩潰市咽。
解決辦法:
大多數(shù)系統(tǒng)設(shè)計(jì)者考慮用加鎖( 最多的解決方案)或者隊(duì)列的方式保證來(lái)保證不會(huì)有大量的線程對(duì)數(shù)據(jù)庫(kù)一次性進(jìn)行讀寫(xiě)痊银,從而避免失效時(shí)大量的并發(fā)請(qǐng)求落到底層存儲(chǔ)系統(tǒng)上。還有一個(gè)簡(jiǎn)單方案就時(shí)講緩存失效時(shí)間分散開(kāi)施绎。
14. 簡(jiǎn)單說(shuō)一說(shuō)緩存穿透以及解決辦法溯革?
緩存穿透是指用戶查詢(xún)數(shù)據(jù),在數(shù)據(jù)庫(kù)沒(méi)有谷醉,自然在緩存中也不會(huì)有致稀。這樣就導(dǎo)致用戶查詢(xún)的時(shí)候,在緩存中找不到孤紧,每次都要去數(shù)據(jù)庫(kù)再查詢(xún)一遍豺裆,然后返回空(相當(dāng)于進(jìn)行了兩次無(wú)用的查詢(xún))。這樣請(qǐng)求就繞過(guò)緩存直接查數(shù)據(jù)庫(kù),這也是經(jīng)常提的緩存命中率問(wèn)題臭猜。
解決辦法:
最常見(jiàn)的則是采用布隆過(guò)濾器躺酒,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè)bitmap攔截掉蔑歌,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢(xún)壓力羹应。
另外也有一個(gè)更為簡(jiǎn)單粗暴的方法,如果一個(gè)查詢(xún)返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在次屠,還是系統(tǒng)故障)园匹,我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過(guò)期時(shí)間會(huì)很短劫灶,最長(zhǎng)不超過(guò)五分鐘裸违。通過(guò)這個(gè)直接設(shè)置的默認(rèn)值存放到緩存,這樣第二次到緩沖中獲取就有值了本昏,而不會(huì)繼續(xù)訪問(wèn)數(shù)據(jù)庫(kù)供汛,這種辦法最簡(jiǎn)單粗暴。
5TB的硬盤(pán)上放滿了數(shù)據(jù)涌穆,請(qǐng)寫(xiě)一個(gè)算法將這些數(shù)據(jù)進(jìn)行排重怔昨。如果這些數(shù)據(jù)是一些32bit大小的數(shù)據(jù)該如何解決?如果是64bit的呢宿稀?
對(duì)于空間的利用到達(dá)了一種極致趁舀,那就是Bitmap和布隆過(guò)濾器(Bloom Filter)。
Bitmap: 典型的就是哈希表
缺點(diǎn)是祝沸,Bitmap對(duì)于每個(gè)元素只能記錄1bit信息矮烹,如果還想完成額外的功能,恐怕只能靠犧牲更多的空間罩锐、時(shí)間來(lái)完成了擂送。
布隆過(guò)濾器(推薦)
就是引入了k(k>1)k(k>1)個(gè)相互獨(dú)立的哈希函數(shù),保證在給定的空間唯欣、誤判率下,完成元素判重的過(guò)程搬味。
它的優(yōu)點(diǎn)是空間效率和查詢(xún)時(shí)間都遠(yuǎn)遠(yuǎn)超過(guò)一般的算法境氢,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。
Bloom-Filter算法的核心思想就是利用多個(gè)不同的Hash函數(shù)來(lái)解決“沖突”碰纬。
Hash存在一個(gè)沖突(碰撞)的問(wèn)題萍聊,用同一個(gè)Hash得到的兩個(gè)URL的值有可能相同。為了減少?zèng)_突悦析,我們可以多引入幾個(gè)Hash寿桨,如果通過(guò)其中的一個(gè)Hash值我們得出某元素不在集合中,那么該元素肯定不在集合中。只有在所有的Hash函數(shù)告訴我們?cè)撛卦诩现袝r(shí)亭螟,才能確定該元素存在于集合中挡鞍。這便是Bloom-Filter的基本思想。
Bloom-Filter一般用于在大數(shù)據(jù)量的集合中判定某元素是否存在预烙。
15. 簡(jiǎn)單說(shuō)一說(shuō)緩存預(yù)熱墨微?
除了緩存服務(wù)器自帶的緩存失效策略之外(Redis默認(rèn)的有6中策略可供選擇),我們還可以根據(jù)具體的業(yè)務(wù)需求進(jìn)行自定義的緩存淘汰扁掸,常見(jiàn)的策略有兩種:
(1)定時(shí)去清理過(guò)期的緩存翘县;
(2)當(dāng)有用戶請(qǐng)求過(guò)來(lái)時(shí),再判斷這個(gè)請(qǐng)求所用到的緩存是否過(guò)期谴分,過(guò)期的話就去底層系統(tǒng)得到新數(shù)據(jù)并更新緩存锈麸。
兩者各有優(yōu)劣,第一種的缺點(diǎn)是維護(hù)大量緩存的key是比較麻煩的牺蹄,第二種的缺點(diǎn)就是每次用戶請(qǐng)求過(guò)來(lái)都要判斷緩存失效忘伞,邏輯相對(duì)比較復(fù)雜!具體用哪種方案钞馁,大家可以根據(jù)自己的應(yīng)用場(chǎng)景來(lái)權(quán)衡虑省。
16. 簡(jiǎn)單說(shuō)一說(shuō)緩存降級(jí)带饱?
當(dāng)訪問(wèn)量劇增烘贴、服務(wù)出現(xiàn)問(wèn)題(如響應(yīng)時(shí)間慢或不響應(yīng))或非核心服務(wù)影響到核心流程的性能時(shí),仍然需要保證服務(wù)還是可用的症杏,即使是有損服務(wù)训措。系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進(jìn)行自動(dòng)降級(jí)伪节,也可以配置開(kāi)關(guān)實(shí)現(xiàn)人工降級(jí)。
降級(jí)的最終目的是保證核心服務(wù)可用绩鸣,即使是有損的怀大。而且有些服務(wù)是無(wú)法降級(jí)的(如加入購(gòu)物車(chē)、結(jié)算)呀闻。
以參考日志級(jí)別設(shè)置預(yù)案:
(1)一般:比如有些服務(wù)偶爾因?yàn)榫W(wǎng)絡(luò)抖動(dòng)或者服務(wù)正在上線而超時(shí)化借,可以自動(dòng)降級(jí);
(2)警告:有些服務(wù)在一段時(shí)間內(nèi)成功率有波動(dòng)(如在95~100%之間)捡多,可以自動(dòng)降級(jí)或人工降級(jí)蓖康,并發(fā)送告警;
(3)錯(cuò)誤:比如可用率低于90%垒手,或者數(shù)據(jù)庫(kù)連接池被打爆了蒜焊,或者訪問(wèn)量突然猛增到系統(tǒng)能承受的最大閥值,此時(shí)可以根據(jù)情況自動(dòng)降級(jí)或者人工降級(jí)科贬;
(4)嚴(yán)重錯(cuò)誤:比如因?yàn)樘厥庠驍?shù)據(jù)錯(cuò)誤了泳梆,此時(shí)需要緊急人工降級(jí)。
服務(wù)降級(jí)的目的,是為了防止Redis服務(wù)故障优妙,導(dǎo)致數(shù)據(jù)庫(kù)跟著一起發(fā)生雪崩問(wèn)題乘综。因此,對(duì)于不重要的緩存數(shù)據(jù)鳞溉,可以采取服務(wù)降級(jí)策略瘾带,例如一個(gè)比較常見(jiàn)的做法就是,Redis出現(xiàn)問(wèn)題熟菲,不去數(shù)據(jù)庫(kù)查詢(xún)看政,而是直接返回默認(rèn)值給用戶。
17.Redis 常見(jiàn)性能問(wèn)題和解決方案抄罕?
(1) Master 最好不要做任何持久化工作允蚣,如 RDB 內(nèi)存快照和 AOF 日志文件
(2) 如果數(shù)據(jù)比較重要,某個(gè) Slave 開(kāi)啟 AOF 備份數(shù)據(jù)呆贿,策略設(shè)置為每秒同步一次
(3) 為了主從復(fù)制的速度和連接的穩(wěn)定性嚷兔, Master 和 Slave 最好在同一個(gè)局域網(wǎng)內(nèi)
(4) 盡量避免在壓力很大的主庫(kù)上增加從庫(kù)
(5) 主從復(fù)制不要用圖狀結(jié)構(gòu),用單向鏈表結(jié)構(gòu)更為穩(wěn)定做入,即: Master <- Slave1 <- Slave2 <- Slave3…
18.Redis如何實(shí)現(xiàn)分布式鎖冒晰?
1.根據(jù)lockKey區(qū)進(jìn)行setnx(set not exist,如果key值為空竟块,則正常設(shè)置壶运,返回1,否則不會(huì)進(jìn)行設(shè)置并返回0)操作浪秘,如果設(shè)置成功蒋情,表示已經(jīng)獲得鎖,否則并沒(méi)有獲取鎖耸携。
2.如果沒(méi)有獲得鎖棵癣,去Redis上拿到該key對(duì)應(yīng)的值,在該key上我們存儲(chǔ)一個(gè)時(shí)間戳(用毫秒表示夺衍,t1)狈谊,為了避免死鎖以及其他客戶端占用該鎖超過(guò)一定時(shí)間(5秒),使用該客戶端當(dāng)前時(shí)間戳沟沙,與存儲(chǔ)的時(shí)間戳作比較的畴。
3.如果沒(méi)有超過(guò)該key的使用時(shí)限,返回false尝胆,表示其他人正在占用該key,不能強(qiáng)制使用护桦;如果已經(jīng)超過(guò)時(shí)限含衔,那我們就可以進(jìn)行解鎖,使用我們的時(shí)間戳來(lái)代替該字段的值。
4.但是如果在setnx失敗后贪染,get該值卻無(wú)法拿到該字段時(shí)缓呛,說(shuō)明操作之前該鎖已經(jīng)被釋放,這個(gè)時(shí)候杭隙,最好的辦法就是重新執(zhí)行一遍setnx方法來(lái)獲取其值以獲得該鎖哟绊。
詳細(xì)內(nèi)容可以查看:Redis與Zookeeper實(shí)現(xiàn)分布式鎖的區(qū)別(https://www.cnblogs.com/mengchunchen/p/9647756.html)
19.如何保證緩存與數(shù)據(jù)庫(kù)雙寫(xiě)時(shí)的數(shù)據(jù)一致性?
你只要用緩存痰憎,就可能會(huì)涉及到緩存與數(shù)據(jù)庫(kù)雙存儲(chǔ)雙寫(xiě)票髓,你只要是雙寫(xiě),就一定會(huì)有數(shù)據(jù)一致性的問(wèn)題铣耘,那么你如何解決一致性問(wèn)題洽沟?
一般來(lái)說(shuō),就是如果你的系統(tǒng)不是嚴(yán)格要求緩存+數(shù)據(jù)庫(kù)必須一致性的話蜗细,緩存可以稍微的跟數(shù)據(jù)庫(kù)偶爾有不一致的情況裆操,最好不要做這個(gè)方案,讀請(qǐng)求和寫(xiě)請(qǐng)求串行化炉媒,串到一個(gè)內(nèi)存隊(duì)列里去踪区,這樣就可以保證一定不會(huì)出現(xiàn)不一致的情況
串行化之后,就會(huì)導(dǎo)致系統(tǒng)的吞吐量會(huì)大幅度的降低吊骤,用比正常情況下多幾倍的機(jī)器去支撐線上的一個(gè)請(qǐng)求缎岗。
還有一種方式就是可能會(huì)暫時(shí)產(chǎn)生不一致的情況,但是發(fā)生的幾率特別小水援,就是先更新數(shù)據(jù)庫(kù)密强,然后再刪除緩存。
這種情況不存在并發(fā)問(wèn)題么蜗元?
不是的或渤。假設(shè)這會(huì)有兩個(gè)請(qǐng)求,一個(gè)請(qǐng)求A做查詢(xún)操作奕扣,一個(gè)請(qǐng)求B做更新操作薪鹦,那么會(huì)有如下情形產(chǎn)生
(1)緩存剛好失效
(2)請(qǐng)求A查詢(xún)數(shù)據(jù)庫(kù),得一個(gè)舊值
(3)請(qǐng)求B將新值寫(xiě)入數(shù)據(jù)庫(kù)
(4)請(qǐng)求B刪除緩存
(5)請(qǐng)求A將查到的舊值寫(xiě)入緩存
ok惯豆,如果發(fā)生上述情況池磁,確實(shí)是會(huì)發(fā)生臟數(shù)據(jù)。
然而楷兽,發(fā)生這種情況的概率又有多少呢地熄?
發(fā)生上述情況有一個(gè)先天性條件,就是步驟(3)的寫(xiě)數(shù)據(jù)庫(kù)操作比步驟(2)的讀數(shù)據(jù)庫(kù)操作耗時(shí)更短芯杀,才有可能使得步驟(4)先于步驟(5)端考⊙盘叮可是,大家想想却特,數(shù)據(jù)庫(kù)的讀操作的速度遠(yuǎn)快于寫(xiě)操作的(不然做讀寫(xiě)分離干嘛扶供,做讀寫(xiě)分離的意義就是因?yàn)樽x操作比較快,耗資源少)裂明,因此步驟(3)耗時(shí)比步驟(2)更短椿浓,這一情形很難出現(xiàn)。
如何解決上述并發(fā)問(wèn)題闽晦?
首先扳碍,給緩存設(shè)有效時(shí)間是一種方案。其次尼荆,采用異步延時(shí)刪除策略左腔,保證讀請(qǐng)求完成以后,再進(jìn)行刪除操作捅儒。
20.是否使用過(guò)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ǔ)。
Slot:插槽阶牍,可以存儲(chǔ)兩個(gè)數(shù)值的一個(gè)變量這個(gè)變量的取值范圍是:0-16383喷面。
Cluster:集群管理者,使集群對(duì)外暴漏的是一個(gè)整體走孽。
redis cluster:采用虛擬分區(qū)的方式惧辈,將整個(gè)集群看成一個(gè)整體,然后分成16384個(gè)槽位磕瓷。
然后再將16484個(gè)槽位分別分配給集群的各個(gè)節(jié)點(diǎn)盒齿,然后各個(gè)節(jié)點(diǎn)各自負(fù)責(zé)一部分槽位。
原理:
節(jié)點(diǎn)1負(fù)責(zé) 0-5000
之間的槽位困食,節(jié)點(diǎn)2負(fù)責(zé)5001-10000
之間的槽位边翁,節(jié)點(diǎn)3負(fù)責(zé)10001-16383
之間的槽位。
k-v鍵值對(duì)數(shù)據(jù)只會(huì)和槽位相關(guān)硕盹,與物理機(jī)器無(wú)關(guān)符匾。通過(guò)crc16算法計(jì)算出 k對(duì)應(yīng)的整數(shù)值(有點(diǎn)類(lèi)似hash),然后對(duì)算出的整數(shù)值%16384取模瘩例,計(jì)算出k-v對(duì)應(yīng)在哪個(gè)槽位上待讳,然后再根據(jù)槽位與機(jī)器節(jié)點(diǎn)的映射關(guān)系芒澜,存儲(chǔ)到相應(yīng)的節(jié)點(diǎn)上去。取的時(shí)候创淡,也是相應(yīng)的過(guò) 程所以整個(gè)集群協(xié)同一致對(duì)外,給client看到的視圖就是完整的數(shù)據(jù)集南吮。
21. redis事物的了解CAS(check-and-set 操作實(shí)現(xiàn)樂(lè)觀鎖 )?
和眾多其它數(shù)據(jù)庫(kù)一樣琳彩,Redis作為NoSQL數(shù)據(jù)庫(kù)也同樣提供了事務(wù)機(jī)制。在Redis中部凑,MULTI/EXEC/DISCARD/WATCH這四個(gè)命令是我們實(shí)現(xiàn)事務(wù)的基石露乏。相信對(duì)有關(guān)系型數(shù)據(jù)庫(kù)開(kāi)發(fā)經(jīng)驗(yàn)的開(kāi)發(fā)者而言這一概念并不陌生,即便如此涂邀,我們還是會(huì)簡(jiǎn)要的列出Redis中事務(wù)的實(shí)現(xiàn)特征:
1). 在事務(wù)中的所有命令都將會(huì)被串行化的順序執(zhí)行瘟仿,事務(wù)執(zhí)行期間,Redis不會(huì)再為其它客戶端的請(qǐng)求提供任何服務(wù)比勉,從而保證了事物中的所有命令被原子的執(zhí)行劳较。
2). 和關(guān)系型數(shù)據(jù)庫(kù)中的事務(wù)相比,在Redis事務(wù)中如果有某一條命令執(zhí)行失敗浩聋,其后的命令仍然會(huì)被繼續(xù)執(zhí)行观蜗。
3). 我們可以通過(guò)MULTI命令開(kāi)啟一個(gè)事務(wù),有關(guān)系型數(shù)據(jù)庫(kù)開(kāi)發(fā)經(jīng)驗(yàn)的人可以將其理解為"BEGIN TRANSACTION"語(yǔ)句衣洁。在該語(yǔ)句之后執(zhí)行的命令都將被視為事務(wù)之內(nèi)的操作墓捻,最后我們可以通過(guò)執(zhí)行EXEC/DISCARD命令來(lái)提交/回滾該事務(wù)內(nèi)的所有操作。這兩個(gè)Redis命令可被視為等同于關(guān)系型數(shù)據(jù)庫(kù)中的COMMIT/ROLLBACK語(yǔ)句坊夫。
4). 在事務(wù)開(kāi)啟之前砖第,如果客戶端與服務(wù)器之間出現(xiàn)通訊故障并導(dǎo)致網(wǎng)絡(luò)斷開(kāi),其后所有待執(zhí)行的語(yǔ)句都將不會(huì)被服務(wù)器執(zhí)行环凿。然而如果網(wǎng)絡(luò)中斷事件是發(fā)生在客戶端執(zhí)行EXEC命令之后梧兼,那么該事務(wù)中的所有命令都會(huì)被服務(wù)器執(zhí)行。
5). 當(dāng)使用Append-Only模式時(shí)拷邢,Redis會(huì)通過(guò)調(diào)用系統(tǒng)函數(shù)write將該事務(wù)內(nèi)的所有寫(xiě)操作在本次調(diào)用中全部寫(xiě)入磁盤(pán)袱院。然而如果在寫(xiě)入的過(guò)程中出現(xiàn)系統(tǒng)崩潰,如電源故障導(dǎo)致的宕機(jī)瞭稼,那么此時(shí)也許只有部分?jǐn)?shù)據(jù)被寫(xiě)入到磁盤(pán)忽洛,而另外一部分?jǐn)?shù)據(jù)卻已經(jīng)丟失。
Redis服務(wù)器會(huì)在重新啟動(dòng)時(shí)執(zhí)行一系列必要的一致性檢測(cè)环肘,一旦發(fā)現(xiàn)類(lèi)似問(wèn)題欲虚,就會(huì)立即退出并給出相應(yīng)的錯(cuò)誤提示。此時(shí)悔雹,我們就要充分利用Redis工具包中提供的redis-check-aof工具复哆,該工具可以幫助我們定位到數(shù)據(jù)不一致的錯(cuò)誤欣喧,并將已經(jīng)寫(xiě)入的部分?jǐn)?shù)據(jù)進(jìn)行回滾。修復(fù)之后我們就可以再次重新啟動(dòng)Redis服務(wù)器了梯找。
22.WATCH命令和基于CAS的樂(lè)觀鎖唆阿?
在Redis的事務(wù)中,WATCH命令可用于提供CAS(check-and-set)功能锈锤。假設(shè)我們通過(guò)WATCH命令在事務(wù)執(zhí)行之前監(jiān)控了多個(gè)Keys驯鳖,倘若在WATCH之后有任何Key的值發(fā)生了變化,EXEC命令執(zhí)行的事務(wù)都將被放棄久免,同時(shí)返回Null multi-bulk應(yīng)答以通知調(diào)用者事務(wù)
執(zhí)行失敗浅辙。例如,我們?cè)俅渭僭O(shè)Redis中并未提供incr命令來(lái)完成鍵值的原子性遞增阎姥,如果要實(shí)現(xiàn)該功能记舆,我們只能自行編寫(xiě)相應(yīng)的代碼。其偽碼如下:
val = GET mykey
val = val + 1
SET mykey $val
以上代碼只有在單連接的情況下才可以保證執(zhí)行結(jié)果是正確的呼巴,因?yàn)槿绻谕粫r(shí)刻有多個(gè)客戶端在同時(shí)執(zhí)行該段代碼泽腮,那么就會(huì)出現(xiàn)多線程程序中經(jīng)常出現(xiàn)的一種錯(cuò)誤場(chǎng)景--競(jìng)態(tài)爭(zhēng)用(race condition)。比如伊磺,客戶端A和B都在同一時(shí)刻讀取了mykey的原有值盛正,假設(shè)該值為10,此后兩個(gè)客戶端又均將該值加一后set回Redis服務(wù)器屑埋,這樣就會(huì)導(dǎo)致mykey的結(jié)果為11豪筝,而不是我們認(rèn)為的12。為了解決類(lèi)似的問(wèn)題摘能,我們需要借助WATCH命令的幫助续崖,見(jiàn)如下代碼:
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
和此前代碼不同的是,新代碼在獲取mykey的值之前先通過(guò)WATCH命令監(jiān)控了該鍵团搞,此后又將set命令包圍在事務(wù)中严望,這樣就可以有效的保證每個(gè)連接在執(zhí)行EXEC之前,如果當(dāng)前連接獲取的mykey的值被其它連接的客戶端修改逻恐,那么當(dāng)前連接的EXEC命令將執(zhí)行失敗像吻。這樣調(diào)用者在判斷返回值后就可以獲悉val是否被重新設(shè)置成功。
23.redis 最適合的場(chǎng)景有哪些复隆?
Redis最適合所有數(shù)據(jù)in-momory
的場(chǎng)景拨匆,雖然Redis也提供持久化功能,但實(shí)際更多的是一個(gè)disk-backed
的功能挽拂,跟傳統(tǒng)意義上的持久化有比較大的差別惭每,那么可能大家就會(huì)有疑問(wèn),似乎Redis更像一個(gè)加強(qiáng)版的Memcached
亏栈,那么何時(shí)使用Memcached
台腥,何時(shí)使用Redis呢?
如果簡(jiǎn)單地比較Redis與Memcached的區(qū)別宏赘,大多數(shù)都會(huì)得到以下觀點(diǎn):
- Redis不僅僅支持簡(jiǎn)單的k/v類(lèi)型的數(shù)據(jù),同時(shí)還提供
list
黎侈,set
察署,zset
,hash
等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)峻汉。 - Redis支持?jǐn)?shù)據(jù)的備份箕母,即
master-slave
模式的數(shù)據(jù)備份。 - Redis支持?jǐn)?shù)據(jù)的持久化俱济,可以將內(nèi)存中的數(shù)據(jù)保持在磁盤(pán)中,重啟的時(shí)候可以再次加載進(jìn)行使用钙勃。
1.會(huì)話緩存(Session Cache)
最常用的一種使用Redis的情景是會(huì)話緩存(session cache)蛛碌。用Redis緩存會(huì)話比其他存儲(chǔ)(如Memcached)的優(yōu)勢(shì)在于:Redis提供持久化。當(dāng)維護(hù)一個(gè)不是嚴(yán)格要求一致性的緩存時(shí)辖源,如果用戶的購(gòu)物車(chē)信息全部丟失蔚携,大部分人都會(huì)不高興的,現(xiàn)在克饶,他們還會(huì)這樣嗎酝蜒?
幸運(yùn)的是,隨著 Redis 這些年的改進(jìn)矾湃,很容易找到怎么恰當(dāng)?shù)氖褂肦edis來(lái)緩存會(huì)話的文檔亡脑。甚至廣為人知的商業(yè)平臺(tái)Magento也提供Redis的插件。
2.全頁(yè)緩存(FPC)
除基本的會(huì)話token之外邀跃,Redis還提供很簡(jiǎn)便的FPC
平臺(tái)霉咨。回到一致性問(wèn)題拍屑,即使重啟了Redis實(shí)例途戒,因?yàn)橛写疟P(pán)的持久化,用戶也不會(huì)看到頁(yè)面加載速度的下降僵驰,這是一個(gè)極大改進(jìn)喷斋,類(lèi)似PHP本地FPC。
再次以Magento為例蒜茴,Magento提供一個(gè)插件來(lái)使用Redis作為全頁(yè)緩存后端星爪。
此外,對(duì)WordPress的用戶來(lái)說(shuō)矮男,Pantheon有一個(gè)非常好的插件 wp-redis移必,這個(gè)插件能幫助你以最快速度加載你曾瀏覽過(guò)的頁(yè)面。
3. 隊(duì)列
Reids在內(nèi)存存儲(chǔ)引擎領(lǐng)域的一大優(yōu)點(diǎn)是提供 list 和 set 操作毡鉴,這使得Redis能作為一個(gè)很好的消息隊(duì)列平臺(tái)來(lái)使用崔泵。Redis作為隊(duì)列使用的操作秒赤,就類(lèi)似于本地程序語(yǔ)言(如Python)對(duì) list 的 push/pop 操作。
如果你快速的在Google中搜索“Redis queues”憎瘸,你馬上就能找到大量的開(kāi)源項(xiàng)目入篮,這些項(xiàng)目的目的就是利用Redis創(chuàng)建非常好的后端工具,以滿足各種隊(duì)列需求幌甘。例如潮售,Celery有一個(gè)后臺(tái)就是使用Redis作為broker,你可以從這里去查看锅风。
4.排行榜/計(jì)數(shù)器
Redis在內(nèi)存中對(duì)數(shù)字進(jìn)行遞增或遞減的操作實(shí)現(xiàn)的非常好酥诽。集合(Set)和有序集合(Sorted Set)也使得我們?cè)趫?zhí)行這些操作的時(shí)候變的非常簡(jiǎn)單,Redis只是正好提供了這兩種數(shù)據(jù)結(jié)構(gòu)皱埠。
所以肮帐,我們要從排序集合中獲取到排名最靠前的10個(gè)用戶–我們稱(chēng)之為“user_scores”,我們只需要像下面一樣執(zhí)行即可:
當(dāng)然边器,這是假定你是根據(jù)你用戶的分?jǐn)?shù)做遞增的排序训枢。如果你想返回用戶及用戶的分?jǐn)?shù),你需要這樣執(zhí)行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一個(gè)很好的例子忘巧,用Ruby實(shí)現(xiàn)的恒界,它的排行榜就是使用Redis來(lái)存儲(chǔ)數(shù)據(jù)的,你可以在這里看到砚嘴。
5.發(fā)布/訂閱
最后(但肯定不是最不重要的)是Redis的發(fā)布/訂閱功能十酣。發(fā)布/訂閱的使用場(chǎng)景確實(shí)非常多。我已看見(jiàn)人們?cè)谏缃痪W(wǎng)絡(luò)連接中使用枣宫,還可作為基于發(fā)布/訂閱的腳本觸發(fā)器婆誓,甚至用Redis的發(fā)布/訂閱功能來(lái)建立聊天系統(tǒng)!(不也颤,這是真的洋幻,你可以去核實(shí))。
Redis提供的所有特性中翅娶,我感覺(jué)這個(gè)是喜歡的人最少的一個(gè)文留,雖然它為用戶提供如果此多功能。
24. 說(shuō)說(shuō)Redis哈希槽的概念竭沫?
Redis集群沒(méi)有使用一致性hash,而是引入了哈希槽的概念燥翅,Redis集群有16384個(gè)哈希槽,每個(gè)key通過(guò)CRC16校驗(yàn)后對(duì)16384取模來(lái)決定放置哪個(gè)槽蜕提,集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分hash槽森书。
25. Redis集群方案什么情況下會(huì)導(dǎo)致整個(gè)集群不可用?
有A,B凛膏,C三個(gè)節(jié)點(diǎn)的集群,在沒(méi)有復(fù)制模型的情況下,如果節(jié)點(diǎn)B失敗了杨名,那么整個(gè)集群就會(huì)以為缺少5501-11000
這個(gè)范圍的槽而不可用。
關(guān)于Redis集群架構(gòu)更加詳細(xì)的內(nèi)容猖毫,可以看看大佬的文章:
那些年用過(guò)的Redis集群架構(gòu)(含面試解析):(https://www.cnblogs.com/rjzheng/p/10360619.html)