【NoSQL】redis基本介紹

hizengzeng發表於2017-06-12

redis簡介

redis是一個key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set –有序集合)和hash(雜湊型別)。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序
Redis支援主從同步。資料可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複製。存檔可以有意無意的對資料進行寫操作。由於完全實現了釋出/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的訊息釋出記錄。同步對讀取操作的可擴充套件性和資料冗餘很有幫助。

redis的安裝,配置等基本引數,基本用法(PHP)

mac安裝redis

#安裝redis
brew install redis

#啟動redis
redis-server

#測試redis是否啟動
redis-cli ping

#連線本機redis
redis-cli
# Redis預設不是以守護程式的方式執行,可以通過該配置項修改,使用yes啟用守護程式
daemonize yes

# 當redis以守護程式方式執行時,Redis預設會把pid寫入/var/run/redis.pid檔案,可以通過pidfile指定
pidfile /var/run/redis.pid

# 預設情況下,redis會響應本機所有可用網路卡的連線請求。當然,redis允許你通過bind配置項來指定要繫結的IP
bind 192.168.1.2 10.8.4.2

# redis的預設服務埠是6379,你可以通過port配置項來修改。如果埠設定為0的話,redis便不會監聽埠了,可以通過unixsocket配置項來指定unix socket檔案的路徑,並通過unixsocketperm來指定檔案的許可權:unixsocket /tmp/redis.sockunixsocketperm 755
port 6379

## TCP 監聽的最大容納數量,在高併發的環境下,你需要把這個值調高以避免客戶端連線緩慢的問題。Linux 核心會一聲不響的把這個值縮小成 /proc/sys/net/core/somaxconn 對應的值,所以你要修改這兩個值才能達到你的預期。
tcp-backlog 511

# 指定在一個 client 空閒多少秒之後服務端關閉連線(0 表示永不關閉)
timeout 0

# TCP連線心跳檢測策略,可以通過tcp-keepalive配置項來進行設定,單位為秒,假如設定為60秒,則server端會每60秒向連線空閒的客戶端發起一次ACK請求,以檢查客戶端是否已經掛掉,對於無響應的客戶端則會關閉其連線。所以關閉一個連線最長需要120秒的時間。如果設定為0,則不會進行心跳檢測
tcp-keepalive 300

#redis支援通過loglevel配置項設定日誌等級,共分四級,即debug、verbose、notice、warning。
loglevel notice

# 日誌儲存目錄
logfile /usr/local/redis/logs/redis.log

# 對於redis來說,可以設定其資料庫的總數量,假如你希望一個redis包含16個資料庫,這16個資料庫的編號將是0到15。預設的資料庫是編號為0的資料庫。使用者可以使用select <DBid>來選擇相應的資料庫
databases 16

# 主要涉及的是redis的RDB持久化相關的配置
save 900 1        # 表示每15分鐘且至少有1個key改變,就觸發一次持久化
save 300 10       # 表示每5分鐘且至少有10個key改變,就觸發一次持久化
save 60 10000     # 表示每60秒至少有10000個key改變,就觸發一次持久化

#預設情況下,如果 redis 最後一次的後臺儲存失敗,redis 將停止接受寫操作,
# 這樣以一種強硬的方式讓使用者知道資料不能正確的持久化到磁碟,
# 否則就會沒人注意到災難的發生
stop-writes-on-bgsave-error yes

# 是否在 dump.rdb 資料庫的時候使用 LZF 壓縮字串,壓縮會佔用CPU資源
rdbcompression yes

# 在儲存快照後,我們還可以讓redis使用CRC64演算法來進行資料校驗
rdbchecksum yes

# 我們還可以設定快照檔案的名稱,
dbfilename dump.rdb

# 設定這個快照檔案存放的路徑
dir ./

# 當一個 slave 與 master 失去聯絡,或者複製正在進行的時候,
# slave 可能會有兩種表現:
#
# 1) 如果為 yes ,slave 仍然會應答客戶端請求,但返回的資料可能是過時,
#    或者資料可能是空的在第一次同步的時候
#
# 2) 如果為 no ,在你執行除了 info he salveof 之外的其他命令時,
#    slave 都將返回一個 "SYNC with master in progress" 的錯誤,
#
slave-serve-stale-data yes

# 你可以配置一個 slave 實體是否接受寫入操作。
# 通過寫入操作來儲存一些短暫的資料對於一個 slave 例項來說可能是有用的,
# 因為相對從 master 重新同步數而言,據資料寫入到 slave 會更容易被刪除。
# 但是如果客戶端因為一個錯誤的配置寫入,也可能會導致一些問題。
slave-read-only yes

# Slaves 在一個預定義的時間間隔內傳送 ping 命令到 server 。
# 你可以改變這個時間間隔。預設為 10 秒
repl-ping-slave-period 10

# 我們可以控制在主從同步時是否禁用TCP_NODELAY。如果開啟TCP_NODELAY,那麼主redis會使用更少的TCP包和更少的頻寬來向從redis傳輸資料。但是這可能會增加一些同步的延遲,大概會達到40毫秒左右。如果你關閉了TCP_NODELAY,那麼資料同步的延遲時間會降低,但是會消耗更多的頻寬
repl-disable-tcp-nodelay no

# 當 master 不能正常工作的時候,Redis Sentinel 會從 slaves 中選出一個新的 master,
# 這個值越小,就越會被優先選中,但是如果是 0 , 那是意味著這個 slave 不可能被選中
slave-priority 100

# 追加模式
appendonly no

# 追加模式的檔名稱
appendfilename "appendonly.aof"

# redis支援三種不同的模式:
# no:不呼叫fsync()。而是讓作業系統自行決定sync的時間。這種模式下,redis的效能會最快。
# always:在每次寫請求後都呼叫fsync()。這種模式下,redis會相對較慢,但資料最安全。
# everysec:每秒鐘呼叫一次fsync()。這是效能和安全的折衷
appendfsync everysec


no-appendfsync-on-rewrite no

# 我們允許redis自動重寫aof。當aof增長到一定規模時,redis會隱式呼叫BGREWRITEAOF來重寫log檔案,以縮減檔案體積。
# redis是這樣工作的:redis會記錄上次重寫時的aof大小。假如redis自啟動至今還沒有進行過重寫,那麼啟動時aof檔案的大小會被作為基準值。
# 這個基準值會和當前的aof大小進行比較。如果當前aof大小超出所設定的增長比例,則會觸發重寫。另外,你還需要設定一個最小大小,是為了防止在aof很小時就觸發重寫
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

# 從伺服器配置
slaveof 10.8.34.29 6379

# 當master服務設定了密碼保護時,slav服務連線master的密碼
masterauth redis123

# 設定Redis連線密碼,如果配置了連線密碼,客戶端在連線Redis時需要通過AUTH <password>命令提供密碼,預設關閉
requirepass redis123

redis持久化

redis支援四種持久化方式,一是 Snapshotting(快照)也是預設方式;二是Append-only file(縮寫aof)的方式;三是虛擬記憶體方式;四是diskstore方式

  • RDB 持久化可以在指定的時間間隔內生成資料集的時間點快照(point-in-time snapshot)。
  • AOF 持久化記錄伺服器執行的所有寫操作命令,並在伺服器啟動時,通過重新執行這些命令來還原資料集。AOF 檔案中的命令全部以 Redis
    協議的格式來儲存,新命令會被追加到檔案的末尾。Redis 還可以在後臺對 AOF 檔案進行重寫(rewrite),使得 AOF檔案的體積不會超出儲存資料集狀態所需的實際大小。
  • Redis 還可以同時使用 AOF 持久化和 RDB 持久化。在這種情況下,當 Redis 重啟時,它會優先使用 AOF
    檔案來還原資料集,因為 AOF 檔案儲存的資料集通常比 RDB 檔案所儲存的資料集更完整。
  • 你甚至可以關閉持久化功能,讓資料只在伺服器執行時存在

RDB優點:

  • RDB 是一個非常緊湊(compact)的檔案,它儲存了 Redis
    在某個時間點上的資料集。這種檔案非常適合用於進行備份:比如說,你可以在最近的 24 小時內,每小時備份一次 RDB

檔案,並且在每個月的每一天,也備份一個 RDB 檔案。這樣的話,即使遇上問題,也可以隨時將資料集還原到不同的版本。

  • RDB 非常適用於災難恢復(disaster
    recovery):它只有一個檔案,並且內容都非常緊湊,可以(在加密後)將它傳送到別的資料中心,或者亞馬遜 S3 中。
  • RDB 可以最大化 Redis 的效能:父程式在儲存 RDB 檔案時唯一要做的就是 fork
    出一個子程式,然後這個子程式就會處理接下來的所有儲存工作,父程式無須執行任何磁碟 I/O 操作。
  • RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。

RDB缺點:

  • 如果你需要儘量避免在伺服器故障時丟失資料,那麼 RDB 不適合你。雖然 Redis 允許你設定不同的儲存點(save
    point)來控制儲存 RDB 檔案的頻率,但是,因為RDB 檔案需要儲存整個資料集的狀態,所以它並不是一個輕鬆的操作。因此你可能會至少5 分鐘才儲存一次 RDB 檔案。在這種情況下,一旦發生故障停機,你就可能會丟失好幾分鐘的資料。
  • 每次儲存 RDB 的時候,Redis 都要 fork() 出一個子程式,並由子程式來進行實際的持久化工作。在資料集比較龐大時,
    fork() 可能會非常耗時,造成伺服器在某某毫秒內停止處理客戶端;如果資料集非常巨大,並且 CPU時間非常緊張的話,那麼這種停止時間甚至可能會長達整整一秒。雖然 AOF 重寫也需要進行 fork() ,但無論 AOF重寫的執行間隔有多長,資料的耐久性都不會有任何損失。

AOF優點:

  • 使用 AOF 持久化會讓 Redis 變得非常耐久(much more durable):你可以設定不同的 fsync 策略,比如無
    fsync ,每秒鐘一次 fsync ,或者每次執行寫入命令時 fsync 。AOF 的預設策略為每秒鐘 fsync一次,在這種配置下,Redis 仍然可以保持良好的效能,並且就算髮生故障停機,也最多隻會丟失一秒鐘的資料( fsync會在後臺執行緒執行,所以主執行緒可以繼續努力地處理命令請求)。
  • AOF 檔案是一個只進行追加操作的日誌檔案(append only log),因此對 AOF 檔案的寫入不需要進行 seek
    ,即使日誌因為某些原因而包含了未寫入完整的命令(比如寫入時磁碟已滿,寫入中途停機,等等),redis-check-aof工具也可以輕易地修復這種問題。
  • Redis 可以在 AOF 檔案體積變得過大時,自動地在後臺對 AOF 進行重寫:重寫後的新 AOF
    檔案包含了恢復當前資料集所需的最小命令集合。整個重寫操作是絕對安全的,因為 Redis 在建立新 AOF檔案的過程中,會繼續將命令追加到現有的 AOF 檔案裡面,即使重寫過程中發生停機,現有的 AOF 檔案也不會丟失。而一旦新 AOF檔案建立完畢,Redis 就會從舊 AOF 檔案切換到新 AOF 檔案,並開始對新 AOF 檔案進行追加操作。
  • AOF 檔案有序地儲存了對資料庫執行的所有寫入操作,這些寫入操作以 Redis 協議的格式儲存,因此 AOF檔案的內容非常容易被人讀懂,對檔案進行分析(parse)也很輕鬆。匯出(export) AOF檔案也非常簡單:舉個例子,如果你不小心執行了 FLUSHALL 命令,但只要 AOF 檔案未被重寫,那麼只要停止伺服器,移除 AOF檔案末尾的 FLUSHALL 命令,並重啟 Redis ,就可以將資料集恢復到 FLUSHALL 執行之前的狀態

AOF 的缺點:

  • 對於相同的資料集來說,AOF 檔案的體積通常要大於 RDB 檔案的體積。
  • 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。在一般情況下,每秒 fsync 的效能依然非常高,而關閉 fsync可以讓 AOF 的速度和 RDB 一樣快,即使在高負荷之下也是如此。不過在處理巨大的寫入載入時,RDB可以提供更有保證的最大延遲時間(latency)。
  • AOF 在過去曾經發生過這樣的 bug :因為個別命令的原因,導致 AOF
    檔案在重新載入時,無法將資料集恢復成儲存時的原樣。(舉個例子,阻塞命令 BRPOPLPUSH 就曾經引起過這樣的 bug)測試套件裡為這種情況新增了測試:它們會自動生成隨機的、複雜的資料集,並通過重新載入這些資料來確保一切正常。雖然這種 bug 在 AOF檔案中並不常見,但是對比來說,RDB 幾乎是不可能出現這種 bug 的

RDB快照原理:
在預設情況下,Redis 將資料庫快照儲存在名字為 dump.rdb 的二進位制檔案中。對 Redis 進行設定,讓它在“ N 秒內資料集至少有 M 個改動”這一條件被滿足時,自動儲存一次資料集

save 900 1        # 900 秒內如果至少有 1 個 key 的值變化,則儲存
save 300 10       # 300 秒內如果至少有 10 個 key 的值變化,則儲存
save 60 10000     # 60 秒內如果至少有 10000 個 key 的值變化,則儲存

當 Redis 需要儲存 dump.rdb 檔案時,伺服器執行以下操作:

  1. Redis 呼叫 fork() ,同時擁有父程式和子程式。
  2. 子程式將資料集寫入到一個臨時 RDB 檔案中。
  3. 當子程式完成對新 RDB 檔案的寫入時,Redis 用新 RDB 檔案替換原來的 RDB 檔案,並刪除舊的 RDB 檔案。

這種工作方式使得 Redis 可以從寫時複製(copy-on-write)機制中獲益

AOF持久化策略及原理:
你可以配置 Redis 多久才將資料 fsync 到磁碟一次。

  • 每次有新命令追加到 AOF 檔案時就執行一次 fsync :非常慢,也非常安全。
  • 每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的資料。
  • 從不 fsync :將資料交給作業系統來處理。更快,也更不安全的選擇。

推薦(並且也是預設)的措施為每秒 fsync 一次,這種 fsync 策略可以兼顧速度和安全性

以下是 AOF 重寫的執行步驟:

  1. Redis 執行 fork() ,現在同時擁有父程式和子程式。
  2. 子程式開始將新 AOF 檔案的內容寫入到臨時檔案。
  3. 對於所有新執行的寫入命令,父程式一邊將它們累積到一個記憶體快取中,一邊將這些改動追加到現有 AOF
    檔案的末尾:這樣即使在重寫的中途發生停機,現有的 AOF 檔案也還是安全的。
  4. 當子程式完成重寫工作時,它給父程式傳送一個訊號,父程式在接收到訊號之後,將記憶體快取中的所有資料追加到新 AOF 檔案的末尾。
  5. 現在 Redis 原子地用新檔案替換舊檔案,之後所有命令都會直接追加到新 AOF 檔案的末尾。

redis叢集介紹

redis的儲存資料結構

redis使用場景

1.取最新N個資料的操作
比如典型的取你網站的最新文章,通過下面方式,我們可以將最新的5000條評論的ID放在Redis的List集合中,並將超出集合部分從資料庫獲取

  • 使用LPUSH latest.comments<ID>命令,向list集合中插入資料
  • 插入完成後再用LTRIM latest.comments 0 5000命令使其永遠只儲存最近5000個ID
  • 然後我們在客戶端獲取某一頁評論時可以用下面的邏輯(虛擬碼)
FUNCTION get_latest_comments(start,num_items):
    id_list = redis.lrange("latest.comments",start,start+num_items-1)
    IF id_list.length < num_items
        id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...")
    END
    RETURN id_list
END

如果你還有不同的篩選維度,比如某個分類的最新N條,那麼你可以再建一個按此分類的List,只存ID的話,Redis是非常高效的。

2.排行榜應用,取TOP N操作
這個需求與上面需求的不同之處在於,前面操作以時間為權重,這個是以某個條件為權重,比如按頂的次數排序,這時候就需要我們的sorted set出馬了,將你要排序的值設定成sorted set的score,將具體的資料設定成相應的value,每次只需要執行一條ZADD命令即可。

3.需要精準設定過期時間的應用
比如你可以把上面說到的sorted set的score值設定成過期時間的時間戳,那麼就可以簡單地通過過期時間排序,定時清除過期資料了,不僅是清除Redis中的過期資料,你完全可以把Redis裡這個過期時間當成是對資料庫中資料的索引,用Redis來找出哪些資料需要過期刪除,然後再精準地從資料庫中刪除相應的記錄。

4.計數器應用
Redis的命令都是原子性的,你可以輕鬆地利用INCR,DECR命令來構建計數器系統。

5.Uniq操作,獲取某段時間所有資料排重值
這個使用Redis的set資料結構最合適了,只需要不斷地將資料往set中扔就行了,set意為集合,所以會自動排重。比如微博共同關注好友

6.實時系統,反垃圾系統
通過上面說到的set功能,你可以知道一個終端使用者是否進行了某個操作,可以找到其操作的集合並進行分析統計對比等。沒有做不到,只有想不到。

7.Pub/Sub構建實時訊息系統
Redis的Pub/Sub系統可以構建實時的訊息系統,比如很多用Pub/Sub構建的實時聊天系統的例子。

8.構建佇列系統
使用list可以構建佇列系統,使用sorted set甚至可以構建有優先順序的佇列系統。

9.快取
這個不必說了,效能優於Memcached,資料結構更多樣化。配合資料庫快取資料

參考資料:
http://blog.csdn.net/is_zhouf…

配置參考:
http://blog.csdn.net/a1282379…
http://www.jianshu.com/p/7970…
http://www.cnblogs.com/kreo/p…
http://doc.redisfans.com/ redis命令查詢
http://blog.nosqlfan.com/html… 使用場景

相關文章