Redis常見面試題(精簡版)

文章目錄

概述
 什麼是Redis
 Redis有哪些數據類型
 Redis有哪些優缺點
 Redis的應用場景
 爲什麼要用 Redis /爲什麼要用緩存
 爲什麼要用 Redis 而不用 map/guava 做緩存?
 Redis爲什麼這麼快
持久化
 什麼是Redis持久化?
 Redis 的持久化機制是什麼?各自的優缺點?
 如何選擇合適的持久化方式
 Redis持久化數據和緩存怎麼做擴容?
過期鍵的刪除策略
 Redis的過期鍵的刪除策略
 Redis key的過期時間和永久有效分別怎麼設置?
內存淘汰策略
 MySQL裏有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據
 Redis的內存淘汰策略
 Redis的內存用完了會發生什麼?
 Redis如何做內存優化?
 Redis回收進程如何工作的?
 Redis回收使用的是什麼算法?
線程模型
 Redis線程模型
事務
 Redis事務
分佈式問題
 Redis實現分佈式鎖
 如何解決 Redis 的併發競爭 Key 問題
 分佈式Redis是前期做還是後期規模上來了再做好?爲什麼?
分區
 Redis是單線程的,如何提高多核CPU的利用率?
 爲什麼要做Redis分區?
 你知道有哪些Redis分區實現方案?
 Redis分區有什麼缺點?
常用工具
 Redis支持的Java客戶端都有哪些?官方推薦用哪個?
 Redis和Redisson有什麼關係?
 Jedis與Redisson對比有什麼優缺點?
其他問題
 Redis與Memcached的區別
 Redis如何做大量數據插入?
 如何保證緩存與數據庫雙寫時的數據一致性?
 Redis常見性能問題和解決方案?
在這裏插入圖片描述

概述

什麼是Redis

Redis(Remote Dictionary Server) 是一個使用 C 語言編寫的,開源的(BSD許可)高性能非關係型(NoSQL)的鍵值對數據庫。

Redis 可以存儲鍵和五種不同類型的值之間的映射。鍵的類型只能爲字符串,值支持五種數據類型:字符串、列表、集合、散列表、有序集合。

與傳統數據庫不同的是 Redis 的數據是存在內存中的,所以讀寫速度非常快,因此 redis 被廣泛應用於緩存方向,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB。另外,Redis 也經常用來做分佈式鎖。除此之外,Redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集羣方案。

Redis有哪些數據類型

Redis主要有5種數據類型,包括String,List,Set,Zset,Hash,滿足大部分的使用要求

數據類型 可以存儲的值 操作
String 字符串、整數或者浮點數 對整個字符串或者字符串的其中一部分執行操作
對整數和浮點數執行自增或者自減操作
List 列表 從兩端壓入或者彈出元素
對單個或者多個元素進行修剪,
只保留一個範圍內的元素
Set 無序集合 添加、獲取、移除單個元素
檢查一個元素是否存在於集合中
計算交集、並集、差集
從集合裏面隨機獲取元素
Hash 包含鍵值對的無序散列表 添加、獲取、移除單個鍵值對
獲取所有鍵值對
檢查某個鍵是否存在
Zset 有序集合 添加、獲取、刪除元素
根據分值範圍或者成員來獲取元素
計算一個鍵的排名

Redis有哪些優缺點

優點

  • 讀寫性能優異, Redis能讀的速度是110000次/s,寫的速度是81000次/s。
  • 支持數據持久化,支持AOF和RDB兩種持久化方式。高版本的Redis支持AOF和RDB混合
  • 支持事務,Redis的所有操作都是原子性的,同時Redis還支持對幾個操作合併後的原子性執行。
  • 數據結構豐富,除了支持string類型的value外還支持hash、set、zset、list等數據結構。
  • 支持主從複製,主機會自動將數據同步到從機,可以進行讀寫分離。

缺點

  • 數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,因此Redis適合的場景主要侷限在較小數據量的高性能操作和運算上。
  • Redis 不具備自動容錯和恢復功能,主機從機的宕機都會導致前端部分讀寫請求失敗,需要等待機器重啓或者手動切換前端的IP才能恢復。
  • 主機宕機,宕機前有部分數據未能及時同步到從機,切換IP後還會引入數據不一致的問題,降低了系統的可用性。
  • Redis 較難支持在線擴容,在集羣容量達到上限時在線擴容會變得很複雜。爲避免這一問題,運維人員在系統上線時必須確保有足夠的空間,這對資源造成了很大的浪費。

Redis的應用場景

  • 計數器:
    1)可以對 String 進行自增自減運算,從而實現計數器功能。
    2)Redis 這種內存型數據庫的讀寫性能非常高,很適合存儲頻繁讀寫的計數量。

  • 緩存:
    1)將熱點數據放到內存中,設置內存的最大使用量以及淘汰策略來保證緩存的命中率。

  • 會話緩存:
    1)可以使用 Redis 來統一存儲多臺應用服務器的會話信息。
    2)當應用服務器不再存儲用戶的會話信息,也就不再具有狀態,一個用戶可以請求任意一個應用服務器,從而更容易實現高可用性以及可伸縮性。

  • 全頁緩存(FPC):
    1)除基本的會話token之外,Redis還提供很簡便的FPC平臺。
    2)以Magento爲例,Magento提供一個插件來使用Redis作爲全頁緩存後端。此外,對WordPress的用戶來說,Pantheon有一個非常好的插件 wp-redis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面。

  • 查找表:
    1)例如 DNS 記錄就很適合使用 Redis 進行存儲。
    2)查找表和緩存類似,也是利用了 Redis 快速的查找特性。但是查找表的內容不能失效,而緩存的內容可以失效,因爲緩存不作爲可靠的數據來源。

  • 消息隊列(發佈/訂閱功能):
    1)List 是一個雙向鏈表,可以通過 lpush 和 rpop 寫入和讀取消息
    2)不過最好使用 Kafka、RabbitMQ 等消息中間件。

  • 分佈式鎖實現:
    1) 在分佈式場景下,無法使用單機環境下的鎖來對多個節點上的進程進行同步。
    2)可以使用 Redis 自帶的 setnx 命令實現分佈式鎖,除此之外,還可以使用官方提供的 RedLock 分佈式鎖實現。

  • 其它
    1)Set 可以實現交集、並集等操作,從而實現共同好友等功能。
    2)ZSet 可以實現有序性操作,從而實現排行榜等功能。

總結:

Redis相比其他緩存,有一個非常大的優勢,就是支持多種數據類型。

數據類型說明string字符串,最簡單的k-v存儲hashhash格式,value爲field和value,適合ID-Detail這樣的場景。list簡單的list,順序列表,支持首位或者末尾插入數據set無序list,查找速度快,適合交集、並集、差集處理sorted set有序的set
其實,通過上面的數據類型的特性,基本就能想到合適的應用場景了。

string:適合最簡單的k-v存儲,類似於memcached的存儲結構,短信驗證碼,配置信息等,就用這種類型來存儲。

hash:一般key爲ID或者唯一標示,value對應的就是詳情了。如商品詳情,個人信息詳情,新聞詳情等。

list:因爲list是有序的,比較適合存儲一些有序且數據相對固定的數據。如省市區表、字典表等。因爲list是有序的,適合根據寫入的時間來排序,如:最新的***,消息隊列等。

set:可以簡單的理解爲ID-List的模式,如微博中一個人有哪些好友,set最牛的地方在於,可以對兩個set提供交集、並集、差集操作。例如:查找兩個人共同的好友等。

Sorted Set:是set的增強版本,增加了一個score參數,自動會根據score的值進行排序。比較適合類似於top 10等不根據插入的時間來排序的數據。

如上所述,雖然Redis不像關係數據庫那麼複雜的數據結構,但是,也能適合很多場景,比一般的緩存數據結構要多。瞭解每種數據結構適合的業務場景,不僅有利於提升開發效率,也能有效利用Redis的性能。

爲什麼要用 Redis /爲什麼要用緩存

主要從“高性能”和“高併發”這兩點來看待這個問題。

高性能:

假如用戶第一次訪問數據庫中的某些數據。這個過程會比較慢,因爲是從硬盤上讀取的。將該用戶訪問的數據存在數緩存中,這樣下一次再訪問這些數據的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內存,所以速度相當快。如果數據庫中的對應數據改變的之後,同步改變緩存中相應的數據即可!
在這裏插入圖片描述

高併發:

直接操作緩存能夠承受的請求是遠遠大於直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去,這樣用戶的一部分請求會直接到緩存這裏而不用經過數據庫。
在這裏插入圖片描述

爲什麼要用 Redis 而不用 map/guava 做緩存?

緩存分爲本地緩存和分佈式緩存。以 Java 爲例,使用自帶的 map 或者 guava 實現的是本地緩存,最主要的特點是輕量以及快速,生命週期隨着 jvm 的銷燬而結束,並且在多實例的情況下,每個實例都需要各自保存一份緩存,緩存不具有一致性。
使用 redis 或 memcached 之類的稱爲分佈式緩存,在多實例的情況下,各實例共用一份緩存數據,緩存具有一致性。缺點是需要保持 redis 或 memcached服務的高可用,整個程序架構上較爲複雜。

Redis爲什麼這麼快

  1. 完全基於內存,絕大部分請求是純粹的內存操作,非常快速。數據存在內存中,類似於 HashMap,HashMap 的優勢就是查找和操作的時間複雜度都是O(1);
  2. 數據結構簡單,對數據操作也簡單,Redis 中的數據結構是專門進行設計的;
  3. 採用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因爲可能出現死鎖而導致的性能消耗;
  4. 使用多路 I/O 複用模型,非阻塞 IO;
  5. 使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis 直接自己構建了 VM 機制 ,因爲一般的系統調用系統函數的話,會浪費一定的時間去移動和請求;

持久化

什麼是Redis持久化?

持久化就是把內存的數據寫到磁盤中去,防止服務宕機了內存數據丟失。

Redis 的持久化機制是什麼?各自的優缺點?

Redis 提供兩種持久化機制 RDB(默認) 和 AOF 機制:

RDB:是Redis DataBase縮寫快照

RDB是Redis默認的持久化方式。按照一定的時間將內存的數據以快照的形式保存到硬盤中,對應產生的數據文件爲dump.rdb。通過配置文件中的save參數來定義快照的週期。
在這裏插入圖片描述
優點:

  • 只有一個文件 dump.rdb,方便持久化。
  • 容災性好,一個文件可以保存到安全的磁盤。
  • 性能最大化,fork 子進程來完成寫操作,讓主進程繼續處理命令,所以是 IO 最大化。使用單獨子進程來進行持久化,主進程不會進行任何 IO 操作,保證了 redis 的高性能
  • 相對於數據集大時,比 AOF 的啓動效率更高。

缺點:

  • 數據安全性低。RDB 是間隔一段時間進行持久化,如果持久化之間 redis 發生故障,會發生數據丟失。所以這種方式更適合數據要求不嚴謹的時候)
  • AOF(Append-only file)持久化方式: 是指所有的命令行記錄以 redis 命令請 求協議的格式完全持久化存儲)保存爲 aof 文件。

AOF:持久化:
AOF持久化(即Append Only File持久化),則是將Redis執行的每次寫命令記錄到單獨的日誌文件中,當重啓Redis會重新將持久化的日誌中文件恢復數據。
當兩種方式同時開啓時,數據恢復Redis會優先選擇AOF恢復。
在這裏插入圖片描述
優點:

  • 數據安全,aof 持久化可以配置 appendfsync 屬性,有 always,每進行一次 命令操作就記錄到 aof 文件中一次。
  • 通過 append 模式寫文件,即使中途服務器宕機,可以通過 redis-check-aof 工具解決數據一致性問題。
  • AOF 機制的 rewrite 模式。AOF 文件沒被 rewrite 之前(文件過大時會對命令 進行合併重寫),可以刪除其中的某些命令(比如誤操作的 flushall))

缺點:

  • AOF 文件比 RDB 文件大,且恢復速度慢。
  • 數據集大的時候,比 rdb 啓動效率低。

優缺點是什麼?

  • AOF文件比RDB更新頻率高,優先使用AOF還原數據。
  • AOF比RDB更安全也更大
  • RDB性能比AOF好
  • 如果兩個都配了優先加載AOF

如何選擇合適的持久化方式

  • 一般來說, 如果想達到足以媲美PostgreSQL的數據安全性,你應該同時使用兩種持久化功能。在這種情況下,當 Redis 重啓的時候會優先載入AOF文件來恢復原始的數據,因爲在通常情況下AOF文件保存的數據集要比RDB文件保存的數據集要完整。
  • 如果你非常關心你的數據, 但仍然可以承受數分鐘以內的數據丟失,那麼你可以只使用RDB持久化。
  • 有很多用戶都只使用AOF持久化,但並不推薦這種方式,因爲定時生成RDB快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比AOF恢復的速度要快,除此之外,使用RDB還可以避免AOF程序的bug。
  • 如果你只希望你的數據在服務器運行的時候存在,你也可以不使用任何持久化方式。

Redis持久化數據和緩存怎麼做擴容?

  • 如果Redis被當做緩存使用,使用一致性哈希實現動態擴容縮容。
  • 如果Redis被當做一個持久化存儲使用,必須使用固定的keys-to-nodes映射關係,節點的數量一旦確定不能變化。否則的話(即Redis節點需要動態變化的情況),必須使用可以在運行時進行數據再平衡的一套系統,而當前只有Redis集羣可以做到這樣。

過期鍵的刪除策略

Redis的過期鍵的刪除策略

我們都知道,Redis是key-value數據庫,我們可以設置Redis中緩存的key的過期時間。Redis的過期策略就是指當Redis中緩存的key過期了,Redis如何處理。

過期策略通常有以下三種:

  • 定時過期:每個設置過期時間的key都需要創建一個定時器,到過期時間就會立即清除。該策略可以立即清除過期的數據,對內存很友好;但是會佔用大量的CPU資源去處理過期的數據,從而影響緩存的響應時間和吞吐量。
  • 惰性過期:只有當訪問一個key時,纔會判斷該key是否已過期,過期則清除。該策略可以最大化地節省CPU資源,卻對內存非常不友好。極端情況可能出現大量的過期key沒有再次被訪問,從而不會被清除,佔用大量內存。
  • 定期過期:每隔一定的時間,會掃描一定數量的數據庫的expires字典中一定數量的key,並清除其中已過期的key。該策略是前兩者的一個折中方案。通過調整定時掃描的時間間隔和每次掃描的限定耗時,可以在不同情況下使得CPU和內存資源達到最優的平衡效果。
    (expires字典會保存所有設置了過期時間的key的過期時間數據,其中,key是指向鍵空間中的某個鍵的指針,value是該鍵的毫秒精度的UNIX時間戳表示的過期時間。鍵空間是指該Redis集羣中保存的所有鍵。)

Redis中同時使用了惰性過期和定期過期兩種過期策略。

Redis key的過期時間和永久有效分別怎麼設置?

EXPIRE和PERSIST命令。

內存淘汰策略

MySQL裏有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據

redis內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。

Redis的內存淘汰策略

Redis的內存淘汰策略是指在Redis的用於緩存的內存不足時,怎麼處理需要新寫入且需要申請額外空間的數據。

  • noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯。
  • allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key。
  • allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key。
  • volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key。
  • volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key。
  • volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除。

總結:
Redis的內存淘汰策略的選取並不會影響過期的key的處理。內存淘汰策略用於處理內存不足時的需要申請額外空間的數據;過期策略用於處理過期的緩存數據。

Redis的內存用完了會發生什麼?

如果達到設置的上限,Redis的寫命令會返回錯誤信息(但是讀命令還可以正常返回。)或者你可以將Redis當緩存來使用配置淘汰機制,當Redis達到內存上限時會沖刷掉舊的內容。

Redis如何做內存優化?

可以好好利用Hash,list,sorted set,set等集合類型數據,因爲通常情況下很多小的Key-Value可以用更緊湊的方式存放到一起。儘可能使用散列表(hashes),散列表(是說散列表裏面存儲的數少)使用的內存非常小,所以你應該儘可能的將你的數據模型抽象到一個散列表裏面。比如你的web系統中有一個用戶對象,不要爲這個用戶的名稱,姓氏,郵箱,密碼設置單獨的key,而是應該把這個用戶的所有信息存儲到一張散列表裏面.

Redis回收進程如何工作的?

  • 一個客戶端運行了新的命令,添加了新的數據。
  • Redis檢查內存使用情況,如果大於maxmemory的限制, 則根據設定好的策略進行回收。
  • 一個新的命令被執行,等等。
  • 所以我們不斷地穿越內存限制的邊界,通過不斷達到邊界然後不斷地回收回到邊界以下。

如果一個命令的結果導致大量內存被使用(例如很大的集合的交集保存到一個新的鍵),不用多久內存限制就會被這個內存使用量超越。

Redis回收使用的是什麼算法?

LRU算法

線程模型

Redis線程模型

Redis基於Reactor模式開發了網絡事件處理器,這個處理器被稱爲文件事件處理器(file event handler)。它的組成結構爲4部分:多個套接字、IO多路複用程序、文件事件分派器、事件處理器。因爲文件事件分派器隊列的消費是單線程的,所以Redis才叫單線程模型。

  • 文件事件處理器使用 I/O 多路複用(multiplexing)程序來同時監聽多個套接字, 並根據套接字目前執行的任務來爲套接字關聯不同的事件處理器。
  • 當被監聽的套接字準備好執行連接應答(accept)、讀取(read)、寫入(write)、關閉(close)等操作時, 與操作相對應的文件事件就會產生, 這時文件事件處理器就會調用套接字之前關聯好的事件處理器來處理這些事件。

雖然文件事件處理器以單線程方式運行, 但通過使用 I/O 多路複用程序來監聽多個套接字, 文件事件處理器既實現了高性能的網絡通信模型, 又可以很好地與 redis 服務器中其他同樣以單線程方式運行的模塊進行對接, 這保持了 Redis 內部單線程設計的簡單性。

參考:https://www.cnblogs.com/barrywxx/p/8570821.html

事務

事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。

事務是一個原子操作:事務中的命令要麼全部被執行,要麼全部都不執行。

Redis事務

Redis事務的概念:

Redis 事務的本質是一組命令的集合。事務支持一次執行多個命令,一個事務中所有命令都會被序列化。在事務執行過程,會按照順序串行化執行隊列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中。

總結說:redis事務就是一次性、順序性、排他性的執行一個隊列中的一系列命令。

  • 事務提供了一種將多個命令打包,然後一次性、有序地執行的機制。
  • 多個命令會入隊到事務隊列中, 然後按先進先出(FIFO)的順序執行。
  • 事務在執行過程中不會被中斷,當事務隊列中的所有命令都被執行完畢之後,事務
    纔會結束。
  • 帶有WATCH命令的事務會將客戶端和被監視的鍵在數據庫的watched_keys字典關聯,當鍵被修改時,程序會將所有監視被修改鍵的客戶端的REDIS_DIRTY_CAS標識打開,服務只有在REDIS_DIRTY_CAS標識沒有打開時,纔會執行客戶端提交的事務,否則服務器拒絕執行事務。
  • Redis事務不支持回滾機制。
  • Redis的事務總是具有ACID中的一致性和隔離性,當服務器運行在AOF持久化模式下,並且appendfsync選項的值爲always時,事務也具有耐久性。

Redis事務沒有隔離級別的概念:

批量操作在發送 EXEC 命令前被放入隊列緩存,並不會被實際執行,也就不存在事務內的查詢要看到事務裏的更新,事務外查詢不能看到。

Redis不保證原子性:

Redis中,單條命令是原子性執行的,但事務不保證原子性,且沒有回滾。事務中任意命令執行失敗,其餘的命令仍會被執行。

Redis事務的三個階段:

  • 開始事務
  • 命令入隊
  • 執行事務

Redis事務相關命令:

Redis事務功能是通過MULTI、EXEC、DISCARD和WATCH 四個原語實現的

Redis會將一個事務中的所有命令序列化,然後按順序執行。

  1. redis 不支持回滾,“Redis 在事務失敗時不進行回滾,而是繼續執行餘下的命令”, 所以 Redis 的內部可以保持簡單且快速。
  2. 如果在一個事務中的命令出現錯誤,那麼所有的命令都不會執行;
  3. 如果在一個事務中出現運行錯誤,那麼正確的命令會被執行。
  • WATCH 命令可以爲 Redis 事務提供 check-and-set (CAS)行爲。 可以監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之後的事務就不會執行,監控一直持續到EXEC命令。
  • MULTI命令用於開啓一個事務,它總是返回OK。 MULTI執行之後,客戶端可以繼續向服務器發送任意多條命令,這些命令不會立即被執行,而是被放到一個隊列中,當EXEC命令被調用時,所有隊列中的命令纔會被執行。
  • EXEC:執行所有事務塊內的命令。返回事務塊內所有命令的返回值,按命令執行的先後順序排列。 當操作被打斷時,返回空值 nil 。
  • 通過調用DISCARD,客戶端可以清空事務隊列,並放棄執行事務, 並且客戶端會從事務狀態中退出。
  • UNWATCH命令可以取消watch對所有key的監控。

分佈式問題

Redis實現分佈式鎖

Redis爲單進程單線程模式,採用隊列模式將併發訪問變成串行訪問,且多客戶端對Redis的連接並不存在競爭關係Redis中可以使用SETNX命令實現分佈式鎖。

當且僅當 key 不存在,將 key 的值設爲 value。 若給定的 key 已經存在,則 SETNX 不做任何動作

SETNX 是『SET If Not Exists』(如果不存在,則 SET)的簡寫。

返回值:設置成功,返回 1 。設置失敗,返回 0 。

在這裏插入圖片描述
使用SETNX完成同步鎖的流程及事項如下:

使用SETNX命令獲取鎖,若返回0(key已存在,鎖已存在)則獲取失敗,反之獲取成功

爲了防止獲取鎖後程序出現異常,導致其他線程/進程調用SETNX命令總是返回0而進入死鎖狀態,需要爲該key設置一個“合理”的過期時間

釋放鎖,使用DEL命令將鎖數據刪除

如何解決 Redis 的併發競爭 Key 問題

所謂 Redis 的併發競爭 Key 的問題也就是多個系統同時對一個 key 進行操作,但是最後執行的順序和我們期望的順序不同,這樣也就導致了結果的不同!

推薦一種方案:分佈式鎖(zookeeper 和 redis 都可以實現分佈式鎖)。(如果不存在 Redis 的併發競爭 Key 問題,不要使用分佈式鎖,這樣會影響性能)

基於zookeeper臨時有序節點可以實現的分佈式鎖。大致思想爲:每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應的指定節點的目錄下,生成一個唯一的瞬時有序節點。 判斷是否獲取鎖的方式很簡單,只需要判斷有序節點中序號最小的一個。 當釋放鎖的時候,只需將這個瞬時節點刪除即可。同時,其可以避免服務宕機導致的鎖無法釋放,而產生的死鎖問題。完成業務流程後,刪除對應的子節點釋放鎖。

在實踐中,當然是從以可靠性爲主。所以首推Zookeeper。

分佈式Redis是前期做還是後期規模上來了再做好?爲什麼?

既然Redis是如此的輕量(單實例只使用1M內存),爲防止以後的擴容,最好的辦法就是一開始就啓動較多實例。即便你只有一臺服務器,你也可以一開始就讓Redis以分佈式的方式運行,使用分區,在同一臺服務器上啓動多個實例。

一開始就多設置幾個Redis實例,例如32或者64個實例,對大多數用戶來說這操作起來可能比較麻煩,但是從長久來看做這點犧牲是值得的。

這樣的話,當你的數據不斷增長,需要更多的Redis服務器時,你需要做的就是僅僅將Redis實例從一臺服務遷移到另外一臺服務器而已(而不用考慮重新分區的問題)。一旦你添加了另一臺服務器,你需要將你一半的Redis實例從第一臺機器遷移到第二臺機器。

分區

Redis是單線程的,如何提高多核CPU的利用率?

可以在同一個服務器部署多個Redis的實例,並把他們當作不同的服務器來使用,在某些時候,無論如何一個服務器是不夠的, 所以,如果你想使用多個CPU,你可以考慮一下分片(shard)。

爲什麼要做Redis分區?

分區可以讓Redis管理更大的內存,Redis將可以使用所有機器的內存。如果沒有分區,你最多隻能使用一臺機器的內存。分區使Redis的計算能力通過簡單地增加計算機得到成倍提升,Redis的網絡帶寬也會隨着計算機和網卡的增加而成倍增長。

你知道有哪些Redis分區實現方案?

  • 客戶端分區就是在客戶端就已經決定數據會被存儲到哪個redis節點或者從哪個redis節點讀取。大多數客戶端已經實現了客戶端分區。
  • 代理分區 意味着客戶端將請求發送給代理,然後代理決定去哪個節點寫數據或者讀數據。代理根據分區規則決定請求哪些Redis實例,然後根據Redis的響應結果返回給客戶端。redis和memcached的一種代理實現就是Twemproxy
  • 查詢路由(Query routing) 的意思是客戶端隨機地請求任意一個redis實例,然後由Redis將請求轉發給正確的Redis節點。Redis Cluster實現了一種混合形式的查詢路由,但並不是直接將請求從一個redis節點轉發到另一個redis節點,而是在客戶端的幫助下直接redirected到正確的redis節點。

Redis分區有什麼缺點?

  • 涉及多個key的操作通常不會被支持。例如你不能對兩個集合求交集,因爲他們可能被存儲到不同的Redis實例(實際上這種情況也有辦法,但是不能直接使用交集指令)。
  • 同時操作多個key,則不能使用Redis事務.
  • 分區使用的粒度是key,不能使用一個非常長的排序key存儲一個數據集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set).
  • 當使用分區的時候,數據處理會非常複雜,例如爲了備份你必須從不同的Redis實例和主機同時收集RDB / AOF文件。
  • 分區時動態擴容或縮容可能非常複雜。Redis集羣在運行時增加或者刪除Redis節點,能做到最大程度對用戶透明地數據再平衡,但其他一些客戶端分區或者代理分區方法則不支持這種特性。然而,有一種預分片的技術也可以較好的解決這個問題。

常用工具

Redis支持的Java客戶端都有哪些?官方推薦用哪個?

Redisson、Jedis、lettuce等等,官方推薦使用Redisson。

Redis和Redisson有什麼關係?

Redisson是一個高級的分佈式協調Redis客服端,能幫助用戶在分佈式環境中輕鬆實現一些Java的對象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。

Jedis與Redisson對比有什麼優缺點?

Jedis是Redis的Java實現的客戶端,其API提供了比較全面的Redis命令的支持;Redisson實現了分佈式和可擴展的Java數據結構,和Jedis相比,功能較爲簡單,不支持字符串操作,不支持排序、事務、管道、分區等Redis特性。Redisson的宗旨是促進使用者對Redis的關注分離,從而讓使用者能夠將精力更集中地放在處理業務邏輯上。

其他問題

Redis與Memcached的區別

兩者都是非關係型內存鍵值數據庫,現在公司一般都是用 Redis 來實現緩存,而且 Redis 自身也越來越強大了!Redis 與 Memcached 主要有以下不同:

對比參數 Redis Memcached
類型 1. 支持內存 2. 非關係型數據庫 1. 支持內存 2. 鍵值對形式 3. 緩存形式
數據存儲類型 1. String 2. List 3. Set 4. Hash 5. Sort Set 【俗稱ZSet】 1. 文本型 2. 二進制類型
查詢【操作】類型 1. 批量操作 2. 事務支持 3. 每個類型不同的CRUD 1.常用的CRUD 2. 少量的其他命令
附加功能 1. 發佈/訂閱模式 2. 主從分區 3. 序列化支持 4. 腳本支持【Lua腳本】 1. 多線程服務支持
網絡IO模型 1. 單線程的多路 IO 複用模型 1. 多線程,非阻塞IO模式
事件庫 自封轉簡易事件庫AeEvent 貴族血統的LibEvent事件庫
持久化支持 1. RDB 2. AOF 不支持
集羣模式 原生支持 cluster 模式 沒有原生的集羣模式,需要依靠客戶端來實現往集羣中分片寫入數據
內存管理機制 在 Redis 中,並不是所有數據都一直存儲在內存中,可以將一些很久沒用的 value 交換到磁盤 Memcached 的數據則會一直在內存中,Memcached 將內存分割成特定長度的塊來存儲數據,以完全解決內存碎片的問題。但是這種方式會使得內存的利用率不高,例如塊的大小爲 128 bytes,只存儲 100 bytes 的數據,那麼剩下的 28 bytes 就浪費掉了

(1) memcached所有的值均是簡單的字符串,redis作爲其替代者,支持更爲豐富的數據類型

(2) redis的速度比memcached快很多

(3) redis可以持久化其數據

Redis如何做大量數據插入?

Redis2.6開始redis-cli支持一種新的被稱之爲pipe mode的新模式用於執行大量數據插入工作。

如何保證緩存與數據庫雙寫時的數據一致性?

你只要用緩存,就可能會涉及到緩存與數據庫雙存儲雙寫,你只要是雙寫,就一定會有數據一致性的問題,那麼你如何解決一致性問題?

一般來說,就是如果你的系統不是嚴格要求緩存+數據庫必須一致性的話,緩存可以稍微的跟數據庫偶爾有不一致的情況,最好不要做這個方案,讀請求和寫請求串行化,串到一個內存隊列裏去,這樣就可以保證一定不會出現不一致的情況

串行化之後,就會導致系統的吞吐量會大幅度的降低,用比正常情況下多幾倍的機器去支撐線上的一個請求。

還有一種方式就是可能會暫時產生不一致的情況,但是發生的機率特別小,就是先更新數據庫,然後再刪除緩存。

Redis常見性能問題和解決方案?

  1. Master最好不要做任何持久化工作,包括內存快照和AOF日誌文件,特別是不要啓用內存快照做持久化。
  2. 如果數據比較關鍵,某個Slave開啓AOF備份數據,策略爲每秒同步一次。
  3. 爲了主從複製的速度和連接的穩定性,Slave和Master最好在同一個局域網內。
  4. 儘量避免在壓力較大的主庫上增加從庫
  5. 爲了Master的穩定性,主從複製不要用圖狀結構,用單向鏈表結構更穩定,即主從關係爲:Master<–Slave1<–Slave2<–Slave3…,這樣的結構也方便解決單點故障問題,實現Slave對Master的替換,也即,如果Master掛了,可以立馬啓用Slave1做Master,其他不變。

END!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章