Redis 學習心得

boring發表於2019-07-04

Redis學習心得

沒看redis入門指南這本書之前,我是透過別人的部落格和手冊來學習redis的,所得到的知識零零碎碎,最近兩個星期看完了入門指南這本書get到了許多知識,於是打算分享一篇學習筆記。

redis的key鍵你真的會命名嗎?

提示 Redis 對於鍵的命名並沒有強制的要求,但比較好的實踐是用“物件型別:物件ID:物件屬性”來命名一個鍵,如使用鍵user:1:friends來儲存ID為1的使用者的好友列表。對於多個單詞則推薦使用“.”分隔,一方面是沿用以前的習慣(Redis以前版本的鍵名不能包含空格等特殊字元),另一方面是在 redis-cli 中容易輸入,無需使用雙引號包裹。另外為了日後維護方便,鍵的命名一定要有意義,如 u:1:f的可讀性顯然不如user:1:friends好.

例如:文章ID為1的這篇文章的觀看量要如何命名?

$key = "article:1:view";

ps:雖然採用較短的名稱可以節省儲存空間,但由於鍵值的長度往往遠遠大於鍵名的長度,所以這部分的節省大部分情況下並不如可讀性來得重要。

redis幾條命令一起執行的時候如何保證原子性?

1.事務

Redis中的事務(transaction)是一組命令的集合。事務同命令一樣都是 Redis 的最小執行單位,一個事務中的命令要麼都執行,要麼都不執行。事務的應用非常普遍,如銀行轉賬過程中A給B匯款,首先系統從A的賬戶中將錢划走,然後向B的賬戶增加相應的金額。這兩個步驟必須屬於同一個事務,要麼全執行,要麼全不執行。否則只執行第一步,錢就憑空消失了,這顯然讓人無法接受。


redis> MULTI

OK

redis> SADD "user:1:following" 2

QUEUED

redis> SADD "user:2:followers" 1

QUEUED

redis> EXEC

1) (integer) 1

2) (integer) 1

上面的程式碼演示了事務的使用方式。首先使用MULTI命令告訴Redis:“下面我發給你的命令屬於同一個事務,你先不要執行,而是把它們暫時存起來。”Redis回答:“OK。”

而後我們傳送了兩個 SADD命令來實現關注和被關注操作,可以看到 Redis 遵守了承諾,沒有執行這些命令,而是返回QUEUED表示這兩條命令已經進入等待執行的事務佇列中了。

當把所有要在同一個事務中執行的命令都發給 Redis 後,我們使用 EXEC 命令告訴Redis將等待執行的事務佇列中的所有命令(即剛才所有返回QUEUED的命令)按照傳送順序依次執行。EXEC 命令的返回值就是這些命令的返回值組成的列表,返回值順序和命令的順序相同。

Redis保證一個事務中的所有命令要麼都執行,要麼都不執行。如果在傳送EXEC命令前客戶端斷線了,則 Redis 會清空事務佇列,事務中的所有命令都不會執行。而一旦客戶端傳送了EXEC命令,所有的命令就都會被執行,即使此後客戶端斷線也沒關係,因為Redis中已經記錄了所有要執行的命令。

2.指令碼

有些情況下會不適合使用事務來保證資料操作的原子性,這時候就要用到指令碼。

使用指令碼的好處有如下幾點:
(1)減少網路開銷:如果五條命令最多需要向Redis傳送5次請求,而使用指令碼功能完成同樣的操作只需要傳送一個請求即可,減少了網路往返時延。

(2)原子操作:Redis 會將整個指令碼作為一個整體執行,中間不會被其他命令插入。換句話說在編寫指令碼的過程中無需擔心會出現競態條件,也就無需使用事務。事務可以完成的所有功能都可以用指令碼來實現。

(3)複用:客戶端傳送的指令碼會永久儲存在 Redis 中,這就意味著其他客戶端(可以是其他語言開發的專案)可以複用這一指令碼而不需要使用程式碼完成同樣的邏輯。

redis的持久化

AOF

當使用Redis儲存非臨時資料時,一般需要開啟AOF持久化來降低程式中止導致的資料丟失。AOF可以將Redis執行的每一條寫命令追加到硬碟檔案中,這一過程顯然會降低Redis 的效能,但是大部分情況下這個影響是可以接受的,另外使用較快的硬碟可以提高AOF的效能。

雖然每次執行更改資料庫內容的操作時,AOF都會將命令記錄在AOF檔案中,但是事實上,由於作業系統的快取機制,資料並沒有真正地寫入硬碟,而是進入了系統的硬碟快取。在預設情況下系統每30秒會執行一次同步操作,以便將硬碟快取中的內容真正地寫入硬碟,在這30秒的過程中如果系統異常退出則會導致硬碟快取中的資料丟失。一般來講啟用AOF持久化的應用都無法容忍這樣的損失,這就需要Redis在寫入AOF檔案後主動要求系統將快取內容同步到硬碟中。在 Redis 中我們可以透過 appendfsync 引數設定同步的時機:

# appendfsync always

appendfsync everysec

# appendfsync no

預設情況下Redis採用everysec規則,即每秒執行一次同步操作。always表示每次執行寫入都會執行同步,這是最安全也是最慢的方式。no表示不主動進行同步操作,而是完全交由作業系統來做(即每30秒一次),這是最快但最不安全的方式。一般情況下使用預設值everysec就足夠了,既兼顧了效能又保證了安全。

結語

看完書中的redis內部編碼最佳化,我還是挺不解的,直到看到一篇部落格才恍然大悟。

部落格地址:https://sunznx.com/redis/instagram-redis-p...

本作品採用《CC 協議》,轉載必須註明作者和本文連結