6.面试题--redis、rabbitmq、es
六、Redis部分
1.0講一下你理解的Redis,為什么Redis很快
Redis是一種高性能的,開源的,C語言編寫的非關系型數據庫,可以對關系型數據庫起到補充作用,同時支持持久化,可以將數據同步保存到磁盤
說Redis很快是相對于關系型數據庫如mysql來說的,主要有以下因素
第一,數據結構簡單,所以速度快
第二,直接在內存中讀寫數據,所以速度快
第三,采用多路IO復用模型,減少網絡IO的時間消耗,避免大量的無用操作,所以速度快
第四,單線程避免了線程切換和上下文切換產生的消耗,所以速度快
1.1你常用的Redis的數據存儲結構有哪些,他們的使用場景分別是什么
Redis存儲的是key-value結構的數據,其中key是字符串類型,value有5種常用的數據類型:字符串string、哈希hash、列表 list、集合 set、有序集合 sorted set
String可以用作緩存,計數器,防攻擊,驗證碼、登錄過期等,List可以用來做隊列,秒殺等,Set可以用來去重
1.3Redis每種存儲結構的簡單命令
1.String
set key value 設置指定key的值**,**key相同的情況下,后設置的值覆蓋前設置的值
get key 獲取指定key的值**
setex key seconds value 設置指定key的值,并將key的過期時間設為seconds秒**
setnx key value 只有在key不存在時設置key的值****
2.hash
*●hset key field value將哈希表key中的字段field的值設為value*
*●hget key field 獲取存儲在哈希表中指定字段的值*
*●hdel key field 刪除存儲在哈希表中的指定字段*
*●hkeys key 獲取哈希表中所有字段*
*●hvals key 獲取哈希表中,所有值*
*●hgetall key 獲取在哈希表中指定key的所有字段和值*
*hset 001 name zhangsan ,hset 001 age 20,hset 001 city beijing*
*hget 001 name 結果zhangsan*
*hdel 001 age 刪除age字段*
*hkeys 001 結果 name city*
*hvals 001 結果zhangsan beijing*
*hgetall 001 結果 name zhangsan city beijing*
3.List
*●lpush key value1 [value2] 將一個或多個值插入到列表頭部*
*●lrange key start stop 獲取列表指定范圍內的元素*
*●rpop key 移除并獲取列表最后一個元素*
*●llen key 獲取列表長度*
*●brpop key1 [key2 ] timeout 移出并獲取列表的最后一個元素,如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止*
*lpush list a b c d 在列表中插入多個值*
*lrange list 0 -1,獲取列表中的元素,從0開始到結束。結果一次輸出 d c b a*
*rpop list 結果為a*
*llen list 結果為3*
*brpop list 10 結果為b ,brpop list 10 結果為 c,brpop list 10 結果為d,brpop list 10 列表中沒有元素,阻塞等待10s后結束。*
4.Set
*●sadd key member1 [member2] 向集合添加一個或多個成員*
*●smembers key 返回集合中的所有成員,*
*●scard key 獲取集合的成員數*
*●sinter key1 [key2] 返回給定所有集合的交集*
*●sunion key1 [key2] 返回所有給定集合的并集*
*●sdiff key1 [key2] 返回給定所有集合的差集*
*●srem key member1 [member2] 移除集合中一個或多個成員*
*sadd set1 a b c d m n 向集合添加多個成員,*
*sadd set2 a b c d x y z*
*smembers set1 得到集合所有成員 b d a c m n*
*scard set1 結果為6*
*sinter set1 set2 返回給定集合的交集,結果為a b c d*
*sunion set1 set2 返回給定集合的并集,結果為a b c d m n x y z*
*sdiff set1 set2 返回給定集合的差集,結果為 m n*
*srem set1 m n 移除set1集合中的 m n 成員*
5.sorted set
zadd key score1 member1 [score2 member2] 向有序集合添加一一個或多個成員,或者更新已存在成員的
分數
zrange key start stop [WITHSCORES] 通過索引區間返回有序集合中指定區間內的成員
zincrby key increment member 有序集合中對指定成員的分數加上增量increment
zrem key member [member] 移除有序集合中的一個或多個成員
zadd zset 10. 0 a 9.0 c 6.0 d 8.0 e
zadd zset 12.0 a 后添加的a的分數會覆蓋先添加的
zrange zset 0 -1 結果為 d e c a
zincrby zset 1.0 e,給zset集合中的e元素的分數加一
zrem zset e c ,移除zset集合中的多個成員
通用命令
●keys pattern 查找所有符合給定模式( pattern)的key
●exists key 檢查給定key是否存在
●type key 返回key所儲存的值的類型
●ttl key 返回給定key的剩余生存時間(TTL, time to live),以秒為單位
●del key 該命令用于在key存在是刪除key
1.4你們項目是怎么用Redis的
使用的是Springboot整合的redis,主要用來解決前后端分離后前后端會話問題,以及驗證碼的問題
1.5怎么防止Redis宕機數據丟失問題
通過對Redis持久化,把內存中的數據和命令,保存一份到磁盤中做備份,當Redis發生宕機,重啟服務器的時候,會從磁盤重新加載備份的數據,從而解決數據丟失問題
1.6Redis持久化是什么?有幾種方式
將內存中的數據備份到磁盤的過程,就叫作持久化
Redis持久化主要有兩種方式,RDB和AOF,可以通過修改redis.conf進行配置
RDB是記錄數據快照,而AOF是記錄寫命令的
1.7Redis有了AOF持久化為什么還要RDB?
AOF和RDB各有所長
RDB是記錄數據快照,它的優點是只產生一個持久化文件,體積相對較小,啟動恢復速度快,備份方便,它的缺點是沒辦法做到數據百分百不丟失,因為它是每隔一定時間保存一次
AOF是記錄寫命令,它的優點是格式清晰,容易理解,數據更安全,采用append模式即使持久化過程中宕機,也不影響已經保存的數據,它的缺點是文件體積較大,恢復速度慢
根據實際需要來選擇,通常二者可以結合來使用
1.8Redis內存不夠了怎么辦?
方式一:增加物理內存
方式二:使用淘汰策略,刪掉一些老舊數據
方式三:集群
1.9你們Redis用在哪些業務上?用的什么存儲結構
主要用做緩存,比如:驗證碼,分類緩存,數據字典緩存,權限數據緩存,登錄信息緩存等。
String類型的存儲結構用的比較多,并且使用了Json格式進行序列化。
2.0淘汰策略有哪些?你們用的哪種
volatile-lru :從已設置過期時間的數據集中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過期時間的數據集中挑選將要過期的數據淘汰
volatile-random:從已設置過期時間的數據集中任意選擇數據淘汰
allkeys-lru:從數據集中挑選最近最少使用的數據淘汰
allkeys-random:從數據集中任意選擇數據淘汰
no-enviction:不使用淘汰
2.1Redis事務和Mysql事務的區別
Mysql的事務是基于日志,記錄修改數據前后的狀態來實現的,而Redis的事務是基于隊列實現的
Mysql中的事務滿足原子性:即一組操作要么同時成功,要么同時失敗,
Redis中的事務不滿足原子性,即一組操作中某些命令執行失敗了,其他操作不會回滾
因此對于比較重要的數據,應該存放在mysql中
2.2緩存的執行流程
1.客戶端發起查詢請求
2.判斷緩存中是否有數據
如果有,直接返回
如果沒有,就從數據庫查詢,再把數據同步到緩存
3.返回數據給客戶端
2.3你們怎么保證Redis和Mysql的一致性
我們在代碼中控制,如果數據庫做是寫操作,直接把redis中的對應數據刪除,下次查詢數據會重新寫入緩存。
我們的業務對一致性要求不是很高,因此采用了先操作mysql,后刪除redis。在寫數據庫和刪除緩存行代碼之間如果有查詢請求依然會查詢到Redis中的老數據,但是這種情況非常極端,而且我們的業務也能容忍這種短暫的臟數據。
我還知道其他方案,比如延遲雙刪 , 監聽Mysql事務日志自動同步Redis等。
2.4SpringCache常用注解
@EnableCaching:打在主啟動類上,開啟緩存功能
@Cacheable:打在方法上,表示該方法會開啟緩存,打在類上,表示類中所有的方法都開啟緩存,方法的返回值會自動寫入緩存。如果緩存中已經有數據,方法將不會被調用,而是拿著緩存數據直接返回給客戶端。
@CacheEvict:搭載類或者方法上,會將緩存清除
@CachePut:更新緩存
@Caching:組合操作,要應用于方法的多個緩存操作
@CacheConfig:打在類上,共享的一些常見緩存設置
2.5了解緩存擊穿,穿透,雪崩嗎?怎么處理?
緩存穿透:請求某個Key對應的數據時,在緩存中沒有命中數據,在數據庫中也沒有命中數據,數據庫會返回空,而Redis也不會緩存這個空結果,這就造成了緩存穿透的問題。
解決方案:
一:就是把空對象緩存起來。當第一次從數據庫中查詢出來的結果為空時,我們就將這個空對象加載到緩存,并設置合理的過期時間,這樣,就能夠在一定程度上保障后端數據庫的安全。
二:使用布隆過濾器來判斷數據庫中有沒有這個key。
緩存擊穿:緩存中沒有,數據庫中有的數據,由于某種原因比如緩存過期了,同時并發用戶特別多,一時間都往數據庫中讀取數據.
解決方案:加互斥鎖,只能允許一個線程訪問數據庫;設置熱點代碼永不過期。
緩存雪崩:緩存重啟,或者大量key失效,導致大量并發打到數據庫
解決方案:
緩存數據的過期時間設置隨機,防止同一時間大量數據過期現象發生。
如果緩存數據庫是分布式部署,將熱點數據均勻分布在不同搞得緩存數據庫中。
設置熱點數據永遠不過期。
2.6Redis的主從有什么優點,和缺點?
優點是讀寫分離,分擔了讀的壓力,同時能起到備份作用,防止數據丟失
缺點是不能分擔寫的壓力,主的單點故障沒有解決,存儲沒有得到擴容
2.7解釋一下Redis的哨兵模式。哨兵的不足?
當主服務器中斷服務后,可以將一個從服務器升級為主服務器 ,以便繼續提供服務
哨兵就是用來監控主從服務器,實現故障恢復功能的。它會不斷的檢查主服務器和從服務器的健康狀態,當某個服務器出現問題時,可以向管理員發起通知。如果主服務器不可用時,會自動選擇一個從服務器作為新的主服務器,并讓其他的從服務器從新的主服務器復制數據
哨兵也是主從模式,沒有解決寫的壓力,只減輕了讀的壓力,而且存儲也得不到擴容
2.8Redis如何模擬隊列和棧,用什么命令
list控制同一邊進,同一邊出就是棧;list控制一邊進,另一邊出就是隊列
2.9Redis存儲單個對象怎么存,存儲對象集合怎么存
單個對象可以使用String,也可以使用hash
集合對象可以使用hash,以便可以快速的通過field來取值
七、RabbitMQ
1.0RabbitMQ的使用場景
rabbitMQ消息隊列可以用來
做任務的異步處理,提高程序的相應時間,
提高系統穩定性,通過手動確認機制,當消費者出現故障,只要沒有確認簽收,請求的數據都不會丟失可以再次處理
服務解耦,生產者通過MQ與消費者交互
流量削峰,通過異步處理,消息傳到MQ直接返回,接著等待排隊處理,避免了線路擁堵
1.1RabbitMQ如何防止消息丟失
首先,RabbitMQ的消息確認機制,默認是自動簽收,也就是說消息一旦被消費者接收,就自動簽收,消息就從隊列里清除了。因此對于重要的消息,不容丟失的數據,我們需要設置在消費完成后手動簽收。
其次,我們可以將消息持久化,避免消息在消費前MQ宕機,網絡問題等造成的消息丟失
1.2RabbitMQ的交換機有哪幾種
Fanout:廣播,將消息交給所有綁定到交換機的隊列
Direct:定向,把消息交給符合指定routing key的隊列
Topic:通配符,把消息交給符合routing pattern的隊列
1.3消息是如何從發送者到達消費者的(RabbitMQ工作流程)
分為消息發送和消息接收兩個步驟
消息發送:生產者和Broker建立TCP連接,創建信道。通過信道將消息發送給Broker,由Exchange將消息進行轉發到指定的隊列
消息接收:消費者和Broker建立TCP連接 ,創建信道 ,然后監聽指定的隊列,當有消息到達隊列時,Broker默認將消息推送給消費者,消費者就能接收到消息
1.4如何防止消息重復消費
重復消費,一般時由于消費者消費成功后,在給MQ確認簽收的時候出現了網絡波動,MQ沒有接到確認,就會繼續給消費者投遞之前的消息,造成消費者接收到了兩條一樣的消息。
我們可以通過實現消息的冪等性來避免這種情況,比如說讓生產者給每個消息攜帶一個唯一的id,消費者獲取消息后根據這個id去查詢數據庫,如果不存在就正常消費,如果存在了就證明該消息被消費過,直接丟棄
1.5RabbitMQ消息投遞失敗,怎么處理
我們可以設置confirm回調和 returned 回調
比如說,可以在發送消息的時候,把消息詳情包括交換機名,路由鍵,都保存到一個表中,狀態設置為發送中,如果在confirm方法中ack為false,代表發送到交換機失敗 ,就把這個記錄狀態修改為發送失敗
然后我們創建一個定時任務定時掃表,去讀取發送失敗的數據并重新發送,為了優化性能,我們設置重試次數3次,如果3次都失敗了,我們可以采取人工干預
八、ElasticSearch
Lucene創建索引原理
Lucene是基于倒排索引原理來實現的
首先,將原文檔進行分詞處理,形成一個個單獨的單詞,
然后取出標點符號以及停詞,形成詞元,
再將詞元做一些語言相關的處理,比如變成小寫,轉換時態,單復數形式等等,
將得到的詞創建一個字典,按照字母順序排序,合并相同的詞,最終生成一個倒排索引文檔
ES的keyword和text區別
keyword:不分詞,直接建立索引,支持模糊查詢,精確查詢,聚合查詢
text:分詞后建立索引,支持模糊查詢,精確查詢,不支持聚合查詢
keyword通常用于通常用于存儲年齡,性別,郵編,郵箱號碼等等,直接將完整數據保存的場景
text通常存儲全文搜索的數據,例如地址,文章內容的保存
ES的優勢
ES是基于Lucene的開源搜索引擎,它解決了原生Lucene使用的不足,優化了Lucene的調用方式
分布式的實時文件存儲,每個字段都被索引并可被搜索
支持實時分析搜索
可以擴展到上百臺服務器,處理PB級結構化或非結構化數據
通過簡單的 RESTful API、可以跟各種語言的客戶端甚至命令行進行交互
上手非常容易,只需很少的學習就可以在生產環境中使用
ES為什么那么快(ES用到什么數據結構)
傳統搜索比如mysql的like關鍵字查詢,它的搜索方式就是全文掃表,查詢性能很低
ES是基于Lucene的全文檢索引擎,它采用的是倒排索引結構,在存儲時先對文檔進行分詞,再做一些標點符號去除,大小寫時態轉換等優化處理,最后按照字母順序去重排序,形成一個倒排索引文檔,我們在檢索時,就可以通過二分查找的方式找到目標值
ES的分層結構,index下面是什么
Index:索引庫,包含有一堆相似結構的文檔數據,類比Mysql中的數據庫
Type:類型,它是index中的一個邏輯數據分類,類比Mysql中的表
Document:文檔:是ES中的最小數據單元,通常用json結構標識,類比Mysql中的一行數據
Field:字段:類比Mysql中的一個列
從ES7.0開始,Type被干掉了,從此庫表合一即一個Index中只有一個默認的Type
講幾個ES中的查詢對象:比如TermQuery
BooleanQuery:按條件查詢
must:查詢條件(模糊查詢)
filter: 過濾條件(精確查詢)
MatchQuery:匹配關鍵字查詢(關鍵字分詞后)
TermQuery:匹配關鍵字查詢(關鍵詞不分詞)
matchAllQuery:匹配所有文檔查詢
rangeQuery:查詢指定范圍內的數據
你簡單描述一下DSL語法
DSL是一種以json形式標識的,由ES提供的一種查詢語言,它由兩部分組成,DSL查詢和DSL過濾。
DSL過濾類似于精確查詢,DSL查詢類似于模糊查詢
你使用過ES的哪些聚合查詢?
指標聚合,比如求和,求最大值,最小值,平均數
數量統計聚合,計算滿足條件數據的總條數,相當于sql中的count
去重聚合,它會計算非重復的數據個數,相當于sql中的distinct
桶聚合,它會將某個field的每個唯一值當成一個桶,并計算每個桶內的文檔個數,相當于sql中的group by
最高權值聚合,它會匹配每組前n條數據,相當于sql中的group by后取出前n條
你們ES和數據庫的數據一致性怎么做的
代碼控制的,數據庫做了寫操作,直接更新ES中的數據,我知道可以通過 Logstash 中數據和ES的數據自動同步。
描述一下ES添加文檔的過程
(1) 客戶端請求一個協調節點coordinating node
(2) 協調節點根據算法選擇一個primary shard: 算法 hash(document_id) % (num_of_primary_shards)
(3) 對應的primary shard 所在節點保存完數據后,將數據同步到replica node。
(4) 協調節點coordinating node 發現 primary node 和所有 replica node 都搞定之后返回結果給客戶端
詳細描述一下Elasticsearch更新和刪除文檔的過程
刪除和更新也都是寫操作,但是Elasticsearch中的文檔是不可變的,因此不能被刪除或者改動以展示其變更; 磁盤上的每個段都有一個相應的.del文件。當刪除請求發送后,文檔并沒有真的被刪除,而是在.del文件中被標記為刪除。該文檔依然能匹配查詢,但是會在結果中被過濾掉。當段合并時,在.del文件中被標記為刪除的文檔將不會被寫入新段。
在新的文檔被創建時,Elasticsearch會為該文檔指定一個版本號,當執行更新時,舊版本的文檔在.del文件中被標記為刪除,新版本的文檔被索引到一個新段。舊版本的文檔依然能匹配查詢,但是會在結果中被過濾掉。
ES有幾種節點類型?他們的作用分別是什么
分為主節點,node.master =true , 數據節點node.data =true , 負載均衡節點(node.data =false,node.master=false),
node.master=true,代表該節點有成為主資格 ,主節點的主要職責是和集群操作相關的內容,如創建或刪除索引,跟蹤哪些節點是群集的一部分,并決定哪些分片分配給相關的節點。一般會把主節點和數據節點分開
node.data=true,數據節點主要是存儲索引數據的節點,主要對文檔進行增刪改查操作,聚合操作等,數據節點對CPU,IO,內存要求較高,優化節點的時候需要做狀態監控,資源不夠時要做節點擴充
當主節點和數據節點配置都設置為false的時候,該節點只能處理路由請求,處理搜索,分發索引操作等,從本質上來說該客戶節點表現為智能負載平衡器。配置:mode.master=false,mode.data=false
ES集群的三種顏色代表什么
綠色,黃色,紅色,綠色代表集群健康,所有的主備分片都得到分配,如果有備分片沒有node去分配,集群是黃色,黃色和綠色都是可用狀態,如果有主分片的節點down機,集群不可寫數據,呈現紅色,代表集群不健康。
你們項目怎么使用ES
我們使用的是spring-boot-start-data-elasticsearch這個庫來操作ES,用在大數據的搜索場景,比如商品的發布,搜索功能。
總結
以上是生活随笔為你收集整理的6.面试题--redis、rabbitmq、es的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【连载之一】那些公众号不会告诉你的职业真
- 下一篇: 计算机left函数的意思,Excel中L