天天看點

搞明白redis的這些問題,你就是redis高手

什麼是redis?

Redis 本質上是一個 Key-Value 類型的記憶體資料庫, 整個資料庫加載在記憶體當中進行操作, 定期通過異步操作把資料庫資料 flush 到硬碟上進行儲存。

因為是純記憶體操作, Redis 的性能非常出色, 每秒可以處理超過 10 萬次讀寫操作, 是已知性能

最快的 Key-Value DB。

Redis 的出色之處不僅僅是性能, Redis 最大的魅力是支援儲存多種資料結構, 此外單個

value 的最大限制是 1GB, 不像 memcached 隻能儲存 1MB 的資料, 是以 Redis 可以用

來實作很多有用的功能,比方說用他的 List 來做 FIFO 雙向連結清單,實作一個輕量級的高性能

消息隊列服務, 用他的 Set 可以做高性能的 tag 系統等等。

另外 Redis 也可以對存入的Key-Value 設定 expire 時間, 是以也可以被當作一 個功能加強版的 memcached 來用。

Redis 的主要缺點是資料庫容量受到實體記憶體的限制, 不能用作海量資料的高性能讀寫, 是以 Redis 适合的場景主要局限在較小資料量的高性能操作和運算上

相比 memcached 有哪些優勢?

(1) memcached 所有的值均是簡單的字元串, Redis 作為其替代者, 支援更為豐富的資料類型

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

(3) Redis 可以持久化其資料

Redis 的全稱是什麼?

Remote Dictionary Server。

支援哪幾種資料類型?

String、 List、 Set、 Sorted Set、 hashes

Redis 有哪幾種資料淘汰政策?

noeviction:傳回錯誤當記憶體限制達到并且用戶端嘗試執行會讓更多記憶體被使用的指令(大部分的寫入指令, 但 DEL 和幾個例外)

allkeys-lru: 嘗試回收最少使用的鍵(LRU), 使得新添加的資料有空間存放。

volatile-lru: 嘗試回收最少使用的鍵(LRU), 但僅限于在過期集合的鍵,使得新添加的資料有空間存放。

allkeys-random: 回收随機的鍵使得新添加的資料有空間存放。

volatile-random: 回收随機的鍵使得新添加的資料有空間存放,但僅限于在過期集合的鍵。

volatile-ttl: 回收在過期集合的鍵, 并且優先回收存活時間(TTL) 較短的鍵,使得新添加的資料有空間存放。

為什麼 Redis 需要把所有資料放到記憶體中?

Redis 為了達到最快的讀寫速度将資料都讀到記憶體中, 并通過異步的方式将資料寫入磁盤。

是以 Redis 具有快速和資料持久化的特征。 如果不将資料放在記憶體中, 磁盤 I/O 速度為嚴重影響 Redis 的性能。 在記憶體越來越便宜的今天, Redis 将會越來越受歡迎。

Redis支援的資料類型?

String字元串:

格式: set key value

string類型是二進制安全的。意思是redis的string可以包含任何資料。比如jpg圖檔或者序列化的對象 。

string類型是Redis最基本的資料類型,一個鍵最大能存儲512MB。

Hash(哈希)

格式: hmset name key1 value1 key2 value2

Redis hash 是一個鍵值(key=>value)對集合。

Redis hash是一個string類型的field和value的映射表,hash特别适合用于存儲對象。

List(清單)

Redis 清單是簡單的字元串清單,按照插入順序排序。你可以添加一個元素到清單的頭部(左邊)或者尾部(右邊)

格式: lpush name value

在 key 對應 list 的頭部添加字元串元素

格式: rpush name value

在 key 對應 list 的尾部添加字元串元素

格式: lrem name index

key 對應 list 中删除 count 個和 value 相同的元素

格式: llen name

傳回 key 對應 list 的長度

Set(集合)

格式: sadd name value

Redis的Set是string類型的無序集合。

集合是通過哈希表實作的,是以添加,删除,查找的複雜度都是O(1)。

zset(sorted set:有序集合)

格式: zadd name score value

Redis zset 和 set 一樣也是string類型元素的集合,且不允許重複的成員。

不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。

zset的成員是唯一的,但分數(score)卻可以重複。

sds相對c的改進?

擷取長度:c字元串并不記錄自身長度,是以擷取長度隻能周遊一遍字元串,redis直接讀取len即可。

緩沖區安全:c字元串容易造成緩沖區溢出,比如:程式員沒有配置設定足夠的空間就執行拼接操作。而redis會先檢查sds的空間是否滿足所需要求,如果不滿足會自動擴充。

記憶體配置設定:由于c不記錄字元串長度,對于包含了n個字元的字元串,底層總是一個長度n+1的數組,每一次長度變化,總是要對這個數組進行一次記憶體重新配置設定的操作。因為記憶體配置設定涉及複雜算法并且可能需要執行系統調用,是以它通常是比較耗時的操作。

redis連結清單源碼?有什麼特性?

雙端、無環、帶長度記錄、

多态:使用 void* 指針來儲存節點值, 可以通過 dup 、 free 、 match 為節點值設定類型特定函數, 可以儲存不同類型的值。

redis的持久化?

RDB持久化可以手動執行,也可以配置定期執行,可以把某個時間的資料狀态儲存到RDB檔案中,反之,我們可以用RDB檔案還原資料庫狀态。

AOF持久化是通過儲存伺服器執行的指令來記錄狀态的。還原的時候再執行一遍即可。

如何選擇合适的持久化方式?

一般來說, 如果想達到足以媲美 PostgreSQL 的資料安全性, 你應該同時使用兩種持久化功能。 如果你非常關心你的資料, 但仍然可以承受數分鐘以内的資料丢失, 那麼你可以隻使用 RDB 持久化。

有很多使用者都隻使用 AOF 持久化, 但并不推薦這種方式: 因為定時生成 RDB 快照(snapshot) 非常便于進行資料庫備份, 并且 RDB 恢複資料集的速度也要比 AOF 恢複的速度要快, 除此之外, 使用 RDB 還可以避免之前提到的 AOF 程式的 bug。

Redis 叢集方案應該怎麼做? 都有哪些方案?

1.twemproxy, 大概概念是, 它類似于一個代理方式, 使用方法和普通 Redis 無任何差別,設 置 好它 下 屬 的多 個 Redis 實 例 後, 使 用 時在 本 需 要 連接配接 Redis 的 地 方改 為 連接配接twemproxy, 它會以一個代理的身份接收請求并使用一緻性 hash 算法, 将請求轉接到具體 Redis, 将結果再傳回 twemproxy。 使用方式簡便(相對 Redis 隻需修改連接配接端口), 對舊項目擴充的首選。 問題: twemproxy 自身單端口執行個體的壓力, 使用一緻性 hash 後, 對Redis 節點數量改變時候的計算值的改變, 資料無法自動移動到新的節點。

  1. codis, 目前用的最多的叢集方案, 基本和 twemproxy 一緻的效果, 但它支援在 QQ賬号出售 節點數量改變情況下, 舊節點資料可恢複到新 hash 節點。
  2. Redis cluster3.0 自帶的叢集, 特點在于他的分布式算法不是一緻性 hash, 而是 hash槽的概念, 以及自身支援節點設定從節點。 具體看官方文檔介紹。

4.在業務代碼層實作, 起幾個毫無關聯的 Redis 執行個體, 在代碼層, 對 key 進行 hash 計算,

然後去對應的 Redis 執行個體操作資料。 這種方式對 hash 層代碼要求比較高, 考慮部分包括,節點失效後的替代算法方案, 資料震蕩後的自動腳本恢複, 執行個體的監控, 等等

MySQL 裡有 2000w 資料, Redis 中隻存 20w 的資料,

如何保證 Redis 中的資料都是熱點資料?

Redis 記憶體資料集大小上升到一定大小的時候, 就會施行資料淘汰政策

Redis 有哪些适合的場景?

(1)、 會話緩存(Session Cache)

最常用的一種使用 Redis 的情景是會話緩存(session cache)。 用 Redis 緩存會話比其他存儲(如 Memcached) 的優勢在于: Redis 提供持久化。 當維護一個不是嚴格要求一緻性的緩存時, 如果使用者的購物車資訊全部丢失, 大部分人都會不高興的, 現在, 他們還會這樣嗎?

幸運的是, 随着 Redis 這些年的改進, 很容易找到怎麼恰當的使用 Redis 來緩存會話的文檔。 甚至廣為人知的商業平台 Magento 也提供 Redis 的插件。

(2)、 全頁緩存(FPC)

除基本的會話 token 之外, Redis 還提供很簡便的 FPC 平台。 回到一緻性問題, 即使重新開機了 Redis 執行個體, 因為有磁盤的持久化, 使用者也不會看到頁面加載速度的下降, 這是一個極大改進, 類似 PHP 本地 FPC。

再次以 Magento 為例, Magento 提供一個插件來使用 Redis 作為全頁緩存後端。此外, 對 WordPress 的使用者來說, Pantheon 有一個非常好的插件 wp-Redis, 這個插件能幫助你以最快速度加載你曾浏覽過的頁面。

(3)、 隊列

Reids 在記憶體存儲引擎領域的一大優點是提供 list 和 set 操作,這使得 Redis 能作為一個很好的消息隊列平台來使用。 Redis 作為隊列使用的操作, 就類似于本地程式語言(如Python) 對 list 的 push/pop 操作。

如果你快速的在 Google 中搜尋“Redis queues”, 你馬上就能找到大量的開源項目, 這些項目的目的就是利用 Redis 建立非常好的後端工具, 以滿足各種隊列需求。 例如, Celery有一個背景就是使用 Redis 作為 broker, 你可以從這裡去檢視。

(4)、 排行榜/計數器

Redis在記憶體中對數字進行遞增或遞減的操作實作的非常好。集合(Set)和有序集合(Sorted Set) 也使得我們在執行這些操作的時候變的非常簡單, Redis 隻是正好提供了這兩種資料結構。 是以, 我們要從排序集合中擷取到排名最靠前的 10 個使用者–我們稱之為“user_scores”, 我們隻需要像下面一樣執行即可:

當然, 這是假定你是根據你使用者的分數做遞增的排序。 如果你想傳回使用者及使用者的分數, 你需要這樣執行:

ZRANGE user_scores 0 10 WITHSCORES

Agora Games 就是一個很好的例子, 用 Ruby 實作的, 它的排行榜就是使用 Redis 來存儲資料的, 你可以在這裡看到。

(5)、 釋出/訂閱

最後 是 Redis 的釋出/訂閱功能。 釋出/訂閱的使用場景确實非常多。 我已看見人們在社交網絡連接配接中使用, 還可作為基于釋出/訂閱的腳本觸發器, 甚至用 Redis 的釋出/訂閱功能來建立聊天系統。

說說 Redis 哈希槽的概念?

Redis 叢集沒有使用一緻性 hash,而是引入了哈希槽的概念, Redis 叢集有 16384 個哈希槽,每個 key 通過 CRC16 校驗後對 16384 取模來決定放置哪個槽, 叢集的每個節點負責一部分hash 槽。