Redis、ES、Nginx和RabbitMQ面试回忆
文章目錄
- Nginx
- 為什么要用Nginx,有什么特點?
- 什么是正向代理和反向代理
- Nginx 有哪些負載均衡策略?
- 為什么要做動靜分離?
- RabbitMQ
- AMQP是什么?
- AMQP模型的幾大組件?
- 為什么使用MQ?MQ的優點
- MQ如何快速實現流量削峰填谷?
- MQ怎么解決消息的重復問題
- RabbitMQ中有哪組件?
- RabbitMQ的工作模式
- MQ消息如何分發?
- 如何確保消息正確地發送至 RabbitMQ?
- 如何確保消息接收方消費了消息?
- 如何保證RabbitMQ消息的可靠傳輸?
- 什么是死信隊列?
- 死信隊列的來源
- 如何配置死信隊列?
- 什么是延時隊列
- 延時隊列的設置
- 消費者消息確認機制
- 消費者消息拒絕
- 消費者消費模式
- 大量堆積消息如何處理
- MQ是如何解決消息有序性的
- MQ是如何實現限流的?
- ES
- 什么是ElasticSearch?
- ES的分詞器?
- 倒排索引?
- ES和Mysql的區別?
- Redis
- 1、 什么是Redis
- 2、 Redis有哪些優缺點
- 3、 為什么要用 Redis /為什么要用緩存
- 4、 Redis的應用場景
- 5、 什么是Redis持久化?有哪些方式
- 6、 Redis的過期鍵的刪除策略
- 7、 MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據
- 8、 Redis的內存淘汰策略有哪些
- 9、 Redis增量復制,全量復制?
- 10、 Redis的內存用完了會發生什么?
- 11、 Redis如何做內存優化?
- 12、 Redis事務相關命令有哪些? (該成功的成功,該失敗的失敗)
- 13、 Redis事務的三個階段?
- 14、 如何解決 Redis 的并發競爭 Key 問題
- 15、 說說Redis的主從復制,讀寫分離,哨兵機制 ,集群
- 16、 如何保證緩存與數據庫雙寫時的數據一致性?
- 17、 說說Redis哈希槽的概念?
- 18、 Redis集群最大節點個數是多少 ?
- 19、 緩存穿透
- 20、 緩存擊穿
- 21、 緩存雪崩
- 22、 緩存傾斜
- 23、 緩存預熱
Nginx
為什么要用Nginx,有什么特點?
穩定性強,占用內存小,并發量高(5W),負載均衡,動靜分離,反向代理。
什么是正向代理和反向代理
- 正向代理是設立在客戶端的,客戶端向代理發送請求,代理向目標服務器轉交請求并將返回結果返回給客戶端。(翻墻軟件,VPN等等)
- 反向代理是配置在服務端的,作用是讓客戶端不知道訪問的是哪一臺服務器,隱藏服務器真正的ip地址。
Nginx 有哪些負載均衡策略?
- 輪詢:平均的分配給每一臺服務器。
- 權重:根據服務器分配的權重值分配。
- ip_hash:根據客戶端請求的ip,分配到不同的服務器上。
為什么要做動靜分離?
Nginx通過動靜分離,來提升Nginx的并發能力,給用戶更快地響應。
RabbitMQ
AMQP是什么?
AMQP是一種協議,RabbitMQ 中的交換器、交換器類型、隊列、綁定、路由鍵等都是遵循的 AMQP 協議中相 應的概念。
AMQP模型的幾大組件?
- 交換器 (Exchange):消息代理服務器中用于把消息路由到隊列的組件。
- 隊列 (Queue):用來存儲消息的數據結構,位于硬盤或內存中。
- 綁定 (Binding):一套規則,告知交換器消息應該將消息投遞給哪個隊列。
為什么使用MQ?MQ的優點
解耦,異步,削峰
- 解耦(降低模塊與模塊之間的耦合):當A系統的接口被多個系統調用,A系統需要考慮調用接口的系統有沒有掛了,需不需要重發等問題,但是如果有了MQ消息隊列,A系統只需要把消息發送給MQ,如果有系統要調用直接消費MQ消息即可,如果沒有就取消消費,這樣A系統就不需要考慮到底要給誰發消息,也不需要考慮發送是否成功,發送超時等問題。
- 異步(提高效率):異步發送消息,從而提高效率。
- 削峰(降低并發請求量):用MQ來降低并發請求到數據庫的數據,給數據庫一定的時間去處理。
MQ如何快速實現流量削峰填谷?
改變MQ的削峰模式,將推模式改為拉模式,定時或者批量拉取可以削平流量,實現自我保護的作用。
但是如果發送流量過大,MQ拉取的速度過慢,就會導致消息的堆積,所以還需要優化消費者,可以采用批量處理的方法提高吞吐量。
MQ怎么解決消息的重復問題
- 重復消費場景:消費者正常消費后正準備發送應答ACK,但此時出現了網絡閃斷,channel斷開連接,消息被再次放入隊列中,導致重復消費。
- 冪等性(例如刪除操作,執行一次和執行多次的操作是一樣的,所以不需要考慮重復消費的問題)
- 使用redis,在消息被消費前,將其采用key為id_0的形式保存在redis中,0代表正在消費,1代表已消費。
RabbitMQ中有哪組件?
RabitMQServer、Vhost、Channel、Exchange、Routing、Queue、Provider、Consumer、Binding
RabbitMQ的工作模式
- Hello-Word(一個生產者,一個默認的交換機,一個隊列,一個消費者)
- Work(一個生產者,一個默認的交換機,一個隊列,兩個消費者)
- 交換機采用輪詢發送消息,給第一個發一條,另一個發下一條
- publish(一個生產者,一個交換機,兩個隊列,兩個消費者)
- Routing(一個生產者,一個交換機,兩個隊列,兩個消費者)
- Topic(一個生產者,一個交換機,兩個隊列,兩個消費者)
MQ消息如何分發?
根據交換機的路由鍵進行分發到MQ中。
如何確保消息正確地發送至 RabbitMQ?
開啟Confirm確認機制,當消息由提供者送到交換機時,調用回調函數確認已送達到交換機。
開啟Return返回機制,確認消息被送達到對應的隊列中。
如何確保消息接收方消費了消息?
手動ACK
如何保證RabbitMQ消息的可靠傳輸?
在生產者發送消息的時候,使用confirm確認機制確保消息到達exchange,采用return返回機制來確保消息抵達queue,最后使用redis避免重復消費消息。
什么是死信隊列?
死信隊列的作用就是避免消息的丟失。一般來說,consumer從隊列中取出消息進行消費,但由于某些原因導致隊列中的某些消息無法被消費,這種消息如果沒有后續的處理,如果配置了死信隊列就會丟進死信隊列中,如果沒有配置死信隊列則被丟棄。
死信隊列的來源
- 消息被拒絕,也就是Reject/Nack,并且requeue=false;
- ttl時間過期;
- 隊列中滿了,無法繼續添加數據到MQ中。
如何配置死信隊列?
@Beanpublic Queue businessQueue(){Map<String, Object> args = new HashMap<>();//這里聲明當前隊列綁定的死信交換機args.put("x-dead-letter-exchange", "deadLetterExchange");//這里聲明當前隊列的死信路由keyargs.put("x-dead-letter-routing-key", "dle.err");return new Queue("businessQueue",true,false,false,args);}什么是延時隊列
延時隊列存儲的就是延時消息,延時消息就是當消息發送后,不讓消費者第一時間立即消費,而是等待一段時間后,消費者才拿到消息消費。
延時隊列的設置
Map<String, Object> args = new HashMap<String, Object>(); args.put("x-message-ttl", 6000);// 但是毫秒 channel.queueDeclare(queueName, durable, exclusive, autoDelete, args);消費者消息確認機制
自動ACK:MQ只需要確認消息發送成功,不需要等待應答直接丟棄消息。(如果出現斷電或者網絡異常就會出現消息丟失的問題)
手動ACK:如果消費者端出現了異常,那么大量消息就會堆積在Unacked消息中,導致消息阻塞。
NACK:通知MQ把消息放回隊列頭部。(如果消費者有問題,就算放回頭部,消費者再次消費,還是出錯又被放回隊列,陷入死循環中)
消費者消息拒絕
basicReject/basicNack
消費者消費模式
MQ的消費模式分為兩種,一種是MQ把消息推給消費者,另外一種是消費者從MQ隊列中拉去消息。
推模式采用BasicConsume,拉模式采用BasicGet
大量堆積消息如何處理
出現的原因:網絡異常,消費者出現異常,沒有ACK。
采用多線程發送到更多的MQ中,提高吞吐量
MQ是如何解決消息有序性的
- 在發送消息的時候就要確定消息的有序性。
- 在消費者消費消息的時候判斷一下他的上一個是否被消費了。
- 如果上一個消費了,可以被消費,消費完后需要將消費記錄放到Redis中存儲,如果上一個消息還未被消費,直接返回Nack。
MQ是如何實現限流的?
設置MQ隊列的最大長度。
ES
什么是ElasticSearch?
Elasticsearch是一個基于Lucene的搜索引擎框架。
ES的分詞器?
比如說“蘋果”,將其分成“蘋”和“果”和“蘋果”進行匹配,出現次數最多的匹配度最高。
倒排索引?
在搜索引擎中,每一個文檔都有一個對應的文檔Id,文檔內容表現為一系列關鍵詞的集合。那么,倒排索引就是關鍵詞對文檔Id的映射,每個關鍵詞都對應著一系列的文件。其中記錄了關鍵詞Id,在文檔中出現的次數以及在文檔中的位置。
ES和Mysql的區別?
- Mysql的庫對應ES的索引。
- Mysql的表對應ES的類型。
- Mysql的一條數據對應ES的Document。
- Mysql的屬性字段對應ES的Field。
Redis
1、 什么是Redis
- 關系型數據庫以表格形式存儲,數據表可以彼此關聯協作存儲。
- 非關系型數據庫不適合存儲在數據表的行和列中,而是大塊組合在一起,一般強調的是數據最終一致性。
- Redis是一個高性能的key-value非關系型數據庫。
- 支持數據持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以重新加載使用。
- 除了支持key-value類型的數據外,還支持set,list,zset,hash等數據結構的存儲。
- 支持數據的備份,即master-slave模式的數據備份。
2、 Redis有哪些優缺點
優勢:
- 性能高,Redis讀寫的速度非常快。
- 豐富的數據類型,支持String,List,Hash,Set等數據類型。
- 事務。
- 持久化。
- 支持主從模式備份,讀寫分離。
缺點:
一旦Redis宕機后,沒有任何容錯機制。
3、 為什么要用 Redis /為什么要用緩存
高性能,高并發,減少和數據庫的交互。
4、 Redis的應用場景
- 服務注冊和發現
- 緩存服務器。
- 自增自減
5、 什么是Redis持久化?有哪些方式
RDB(Redis DataBase):
用快照的方式,保存內存結構(二進制文件)
- 優點:加載速度快。
- 缺點:數據安全性低。
AOF(Append-only-file):
把寫的命令全部保存到文件。
- 優點:數據安全。
- 缺點:AOF文件大,且數據恢復速度慢。
6、 Redis的過期鍵的刪除策略
- 惰性刪除:每次獲取鍵的時候,檢查鍵是否過期,如果鍵過期就刪除鍵,沒過期就返回鍵。
- 定期刪除:每隔一段時間就對redis數據庫進行檢查,刪除里面的過期鍵,但刪除多少過期鍵和檢查多少個數據庫由算法決定。
- 定時刪除:太消耗資源不推薦。
7、 MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據
- 1.當第一次從MySql獲取數據的時候,將其存在redis中并設置過期時間,以后每次查詢redis中的數據時判斷是否還在redis中,如果存在就給他延長過期時間,以此來保證redis中的數據都是熱點數據。
- 2.使用淘汰策略。
8、 Redis的內存淘汰策略有哪些
- LRU(Least Recently Used):最近最少使用。
- LFU(Least Frequently Used):最近最少頻繁使用。
- TTL(Time To Live):生存時間最少。
- RANDOM:隨機淘汰。
- 抽取樣本進行淘汰。
9、 Redis增量復制,全量復制?
1.全量復制:
用于節點初始化的情況下,將主節點的所有數據發送給從節點,當數據量特別大的時候,會對主節點和網絡造成很大的一個開銷。
2.增量復制
10、 Redis的內存用完了會發生什么?
要么會發生報錯,要么會調用淘汰策略清除一些key來保證redis的正常運行。
11、 Redis如何做內存優化?
- 1.給每個key都設置生存時間。
- 2.爭對業務場景給出對應的淘汰策略。
- 3.正確使用Redis數據結構。
12、 Redis事務相關命令有哪些? (該成功的成功,該失敗的失敗)
- multi:開啟事務。
- exec:執行事務塊內的所有命令。
- discard:取消事務。
- watch:監聽key在事務執行之前是否改變,若已修改則事務內的事務取消執行。
- unwatch:取消對key的監聽。
13、 Redis事務的三個階段?
- 1.multi:開啟事務。
- 2.添加命令到事務塊中。
- 3.exec/discard:執行事務塊中的命令/取消執行事務塊中的命令。
14、 如何解決 Redis 的并發競爭 Key 問題
setnx
15、 說說Redis的主從復制,讀寫分離,哨兵機制 ,集群
集群解決單點故障(有狀態和無狀態)
管調哪臺服務器返回的結果是一樣的(無)
需要服務器共享數據的(redis,eureka,zookeeper)
- 主從架構:一主多從,作用只是數據備份方案。
- 讀寫分離:主只提供寫的操作,從只提供讀的操作。2.提高Redis讀的速度
- 哨兵機制:對Redis節點的監視和選舉,哨兵數量至少為3個,只要有一半哨兵投票通過,那么選舉出來的就為主節點。
- redis集群沒有主從一說,去中心化,使用hash槽讓key每次訪問的都是同一個redis服務器。
16、 如何保證緩存與數據庫雙寫時的數據一致性?
先刪除緩存,然后更新數據庫,如果這時候有請求發送過來,他會訪問到空的緩存,然后去數據庫中拿數據,如果此時數據庫未更新成功,那么此時緩存中的數據還是舊數據,導致數據庫和緩存中數據不一致,那么就需要延遲一段時間后再刪除一次緩存。(雙刪延遲)
17、 說說Redis哈希槽的概念?
首先,Redis集群中總共有16384個hahs槽,執行寫命令的時候會將key按照一種算法得到一個結果,然后將這個結果對hash槽個數進行取余,然后將key放到這個位置的hash槽中。(Nigix負載均衡中ip_hash用到了hash槽,類似hashmap底層)
18、 Redis集群最大節點個數是多少 ?
16384
19、 緩存穿透
1.出現的原因:
redis中沒有,mysql中也沒有(比如查詢的id為1)
2.如何解決:
設置一個默認值(如果在數據庫中也沒有查詢到數據,就在緩存中存放一個默認值)
對id進行過濾,過濾掉一些不合法的id(比如負數)
20、 緩存擊穿
1.出現的原因:
- 數據庫中有,但redis中沒有(熱點數據突然過期)
- 并發查詢數據庫
2.如何解決:
- 分布式鎖
- 設值熱點數據不過期
21、 緩存雪崩
1.出現的原因:
大量數據在同一時間過期
2.如何解決:
設置數據的過期時間隨機分布在30-60秒內,不讓數據同時過期。
22、 緩存傾斜
1.出現的原因:
高并發請求訪問一個redis服務
2.如何解決:
搭建redis集群和主從架構
23、 緩存預熱
1.出現的原因:
發生在項目上線之前,熱數據需要提前存放在redis中
2.如何解決:
數據量不大可以人工手動導入
定時熱刷新
總結
以上是生活随笔為你收集整理的Redis、ES、Nginx和RabbitMQ面试回忆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 36 个JS 面试题为你助力金九银十(面
- 下一篇: 奋斗的意义