1. 程式人生 > 實用技巧 >AOF和資料型別02

AOF和資料型別02

redis 使用場景

1.快取(redis資料儲存在記憶體)
2.會話保持(生命週期TTL)
3.訊息佇列(list型別)
4.計數器(string型別)
5.QQ,微信共同好友(集合)
6.排行榜(有序集合)
7.儲存(hash型別)

持久化

將記憶體中的資料寫入磁碟

1.持久化模式

1.RDB模式,支援高併發,save
2.AOF模式,資料一致性,

2.RDB模式

可以在指定的時間間隔內生成資料集的'時間點快照'

1)RDB模式工作方式

1.預設情況下,Redis儲存資料集快照到磁碟,名為dump.rdb的二進位制檔案。
你'可以設定'讓Redis在N秒內至少有M次資料集改動時儲存資料集,
或者你也可以手動呼叫SAVE或者BGSAVE命令。
save	:記憶體中的資料寫入磁碟中的時候(dump.rdb),'不支援'資料的寫入
bgsave	:記憶體中的資料寫入磁碟中的時候,'支援'資料的寫入

2.在上文中我們已經在配置檔案中做過對應的配置:
例如,這個配置會讓Redis在每個60秒內至少有1000次鍵改動時自動轉儲資料集到磁碟:
save 60 1000

3.當 Redis 需要儲存 dump.rdb 檔案時,伺服器執行以下操作:(# save原理)
Redis 呼叫 fork() ,同時擁有父程序和子程序。
子程序將資料集寫入到一個臨時的 RDB 檔案中。當子程序完成對新 RDB 檔案的寫入時, Redis 用新RDB 檔案替換原來的 RDB 檔案,並刪除舊的 RDB 檔案。

#Redis關閉的時候自動生成dump.rdb檔案(自動save)

2)配置rdb持久化

#編輯配置檔案
[root@db01 redis]# vim /service/redis/6379/redis.conf
#監聽地址
bind 172.16.1.52 127.0.0.1
#埠
port 6379
#後臺啟動
daemonize yes
#pid檔案位置
pidfile /service/redis/6379/redis_6379.pid
#日誌級別
loglevel notice
#指定日誌檔案
logfile "/service/redis/6379/redis_6379.log"
#設定redis密碼
requirepass 123

#持久化資料檔案儲存位置
dir /etc/redis/6379
#rdb持久化資料檔名
dbfilename dump.rdb
#900秒(15分鐘)內有1個更改
save 900 1
#300秒(5分鐘)內有10個更改
save 300 10
#60秒(1分鐘)內有10000個更改
save 60 10000

#後臺備份程序出錯時,主程序停不停止寫入? 主程序不停止容易造成資料不一致
stop-writes-on-bgsave-error yes
#匯出的rdb檔案是否壓縮 如果rdb的大小很大的話建議這麼做
rdbcompression yes
#匯入rbd恢復時資料時,要不要檢驗rdb的完整性 驗證版本是不是一致
rdbchecksum yes

#持久化預設是rdb模式

3)RDB持久化優點

1.RDB是一種表示某個即時點的Redis資料的緊湊檔案。RDB檔案'適合用於備份'。
例如,你可能想要每小時歸檔最近24小時的RDB檔案,每天儲存近30天的RDB快照。這允許你很容易的恢復不同版本的資料集以容災。
2.RDB非常適合於'災難恢復',作為一個緊湊的單一檔案,可以被傳輸到遠端的資料中心。(Redis不同例項的rdp檔案是'通用'的)
3.RDB最大化了Redis的效能,因為Redis父程序持久化時唯一需要做的是'啟動(fork)一個子程序',
由子程序完成所有剩餘工作。父程序例項不需要執行像磁碟IO這樣的操作。所以Redis服務端不會'阻止資料的寫入'
4.RDB在'重啟' 儲存了大資料集的例項時比AOF要快。(rdb檔案是二進位制檔案)

#dump.rdb檔案記錄的是Redis資料庫的'結果',appendonly.aof檔案記錄的是Redis語句的'過程'
#rdb模式和AOF模式一樣,都是呼叫Fock子程序來寫入磁碟,所以不會阻止客戶端資料的寫入

4)RDB持久化缺點

1.當你需要在Redis停止工作(例如'停電')時最小化資料丟失,RDB可能不太好。
你可以配置不同的儲存點(save point)來儲存RDB檔案(例如,至少5分鐘和對資料集100次寫之後,但是你可以有多個儲存點)。
然而,你通常每隔5分鐘或更久建立一個RDB快照,所以一旦Redis因為任何原因沒有正確關閉而停止工作,你就得做好最近幾分鐘資料丟失的準備了。
2.RDB需要經常呼叫fork()子程序來持久化到磁碟。
如果資料集很大的話,fork()比較耗時,結果就是,當資料集非常大並且CPU效能不夠強大的話,Redis會停止服務客戶端幾毫秒甚至一秒。
AOF也需要fork(),但是你可以'調整多久頻率重寫'日誌而不會有損(trade-off)永續性(durability)。

5)RDB模式優缺點總結

1.優點:速度快,適合於用作備份,主從複製也是基於RDB持久化功能實現的。
2.缺點:會有資料丟失、Fock程序呼叫頻繁導致服務停止幾秒

3.AOF持久化

AOF(append only file)只追加檔案,
記錄伺服器執行的'所有寫操作命令'(類似於mysql的binlog),並在伺服器啟動時,通過重新執行這些命令來還原資料集(指定目錄執行appendonly.aof)。 
AOF 檔案中的命令全部以 Redis 協議的格式來儲存(*之間的那一段是一條命令),新命令會被追加到檔案的末尾。

1)配置AOF持久化

#修改配置檔案
[root@db01 redis]# vim /service/redis/6379/redis.conf
#監聽地址
bind 172.16.1.52 127.0.0.1
#埠
port 6379
#後臺啟動
daemonize yes
#pid檔案位置
pidfile /service/redis/6379/redis_6379.pid
#日誌級別
loglevel notice
#指定日誌檔案
logfile "/service/redis/6379/redis_6379.log"
#設定redis密碼
requirepass 123

#持久化資料檔案儲存位置
dir /etc/redis/6379
#rdb持久化資料檔名
#dbfilename dump.rdb
#900秒(15分鐘)內有1個更改
#save 900 1
#300秒(5分鐘)內有10個更改
#save 300 10
#60秒(1分鐘)內有10000個更改
#save 60 10000

#是否開啟AOF日誌功能
appendonly yes
#每一條命令都立即同步到AOF
appendfsync always
#每秒寫一次
#appendfsync everysec
#寫入工作交給作業系統,由作業系統判斷緩衝區大小,統一寫入到AOF
#appendfsync no

#正在匯出rdb快照的過程中,要不要停止同步aof
no-appendfsync-on-rewrite yes
#aof檔案大小比起上次重寫時的大小,增長率100%時重寫,缺點:業務開始的時候,會重複重寫多次
auto-aof-rewrite-percentage 100
#aof檔案,至少超過64M時,重寫
#auto-aof-rewrite-min-size 64mb

2)AOF模式的優點

1.使用AOF Redis會更具有'可永續性'(durable):
你可以有很多不同的fsync策略:沒有fsync,每秒fsync,每次請求時fsync。
使用'預設的每秒'fsync策略,寫效能也仍然很不錯(fsync是由後臺執行緒完成的,主執行緒繼續努力地執行寫請求),即便損失也就僅僅只損失一秒鐘的寫資料。或幾次資料的寫入
2.AOF日誌是一個追加檔案,所以不需要定位,在斷電時也沒有損壞問題。即使由於某種原因檔案末尾是一個寫到一半的命令(磁碟滿或者其他原因),'redis-check-aof工具'也可以很輕易的修復(刪除壞掉的)。
3.當AOF檔案變得很大時,Redis會'自動在後臺進行重寫'(bgrewriteaof)。重寫是絕對安全的,因為Redis繼續往舊的檔案中追加,使用建立當前資料集所需的最小操作集合來建立一個全新的檔案,一旦第二個檔案建立完畢,Redis就會切換這兩個檔案,並開始往新檔案追加。
4.AOF檔案裡面包含'一個接一個的操'作,以易於理解和解析的格式儲存。你也可以輕易的匯出一個AOF檔案。例如,即使你不小心錯誤地使用FLUSHALL命令清空一切,'如果此時並沒有執行重寫,你仍然可以儲存你的資料集',你只要停止伺服器,刪除最後一條命令,然後重啟Redis就可以。

redis-check-aof

3)AOF重寫功能(bgrewriteaof)

1.因為 AOF 的運作方式是不斷地將命令追加到檔案的末尾,所以隨著寫入命令的不斷增加, AOF 檔案的體積也變得越來越大。舉個例子,如果你對一個計數器呼叫了 100 次 INCR ,那麼僅僅是為了儲存這個計數器的當前值, AOF 檔案就需要使用 100 條記錄。然而在實際上,只使用一條 SET 命令已經足以儲存計數器的當前值了,其餘 99 條記錄實際上都是多餘的。

2.為了處理這種情況, Redis 支援一種有趣的特性:可以在不斷服務客戶端的情況下,對 AOF 檔案進行重建。執行 BGREWRITEAOF 命令, Redis 將生產一個新的 AOF 檔案,這個檔案'包含重建當前資料集所需的最少命令'。使RedisAOF的啟動速度趨近於rdb模式

BGREWRITEAOF

4)AOF持久化缺點

1.對同樣的資料集,AOF檔案通常要'大於'等價的RDB檔案。
2.AOF可能比RDB'慢',這取決於準確的fsync策略。通常fsync設定為每秒一次的話,效能仍然很高,如果關閉fsync,即使在很高的負載下也和RDB一樣的快。不過,即使在很大的寫負載情況下,RDB還是能提供能好的最大延遲保證。

5)AOF持久化優缺點總結

優點:可以最大程度保證資料不丟失
缺點:日誌記錄量級比較大

4.RDB與AOF

1)應該應用哪一個

1.一般來說,如果想達到足以媲美 PostgreSQL 的資料安全性,你應該'同時使用兩種持久化功能。',預設優先讀取AOF,再讀取rdb檔案
2.


2)RDB與AOF相互作用

1.在'版本號大於等於2.4的Redis中',
BGSAVE 執行的過程中,不可以執行 BGRWRITEAOF,
反過來說,在 BGRWRITEAOF 執行的過程中,也不可以執行 BGSAVE 。

2.這可以防止兩個 Redis 後臺程序同時對磁碟進行大量的 I/O 操作。
如果 BGSAVE 正在執行,並且使用者呼叫 BGRWRITEAOF 命令,
那麼伺服器將向用戶回覆一個 OK 狀態,並告知使用者,BGRWRITEAOF 已經被預定執行;一旦 BGSAVE 執行完畢, BGRWRITEAOF 就會正式開始。

3.當 Redis 啟動時,如果 RDB 持久化和 AOF 持久化都被打開了,那麼程式會'優先使用 AOF 檔案來恢復資料集,因為 AOF 檔案所儲存的資料通常是最完整的。'

3)備份Redis資料

1.Redis 對於資料備份是非常友好的,因為你可以在伺服器執行的時候對 RDB 檔案進行復制: RDB 檔案一旦被建立,就不會進行任何修改。
2.當伺服器要建立一個新的 RDB 檔案時,它先將檔案的內容儲存在一個臨時檔案裡面,當臨時檔案寫入完畢時,程式才使用臨時檔案替換原來的 RDB 檔案。(#Redis服務端不會阻止客戶端資料的寫入)
3.這也就是說,無論何時, 複製 RDB 檔案都是絕對安全的。

#以下是我們的建議:
1.建立一個定期任務(cron job), 每小時將一個 RDB 檔案備份到一個資料夾, 並且每天將一個 RDB 檔案備份到另一個資料夾。
2.確保快照的備份都帶有相應的日期和時間資訊, 每次執行定期任務指令碼時, 使用 find 命令來刪除過期的快照: 比如說, 你可以保留最近 48 小時內的每小時快照, 還可以保留最近一兩個月的每日快照。
3.至少每天一次, 將 RDB 備份到你的資料中心之外, 或者至少是備份到你執行 Redis 伺服器的物理機器之外。

4)RDB持久化高階配置

#編輯配置檔案
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#後臺備份程序出錯時,主程序停不停止寫入? 主程序不停止容易造成資料不一致
stop-writes-on-bgsave-error yes
#匯出的rdb檔案是否壓縮 如果rdb的大小很大的話建議這麼做
rdbcompression yes
#匯入rbd恢復時資料時,要不要檢驗rdb的完整性 驗證版本是不是一致
rdbchecksum yes

5)AOF持久化高階配置

#編輯配置檔案
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#正在匯出rdb快照的過程中,要不要停止同步aof
no-appendfsync-on-rewrite yes
#aof檔案大小比起上次重寫時的大小,增長率100%時重寫,缺點:業務開始的時候,會重複重寫多次
auto-aof-rewrite-percentage 100
#aof檔案,至少超過64M時,重寫
#auto-aof-rewrite-min-size 64mb

資料型別

參考網站

各個資料型別應用場景:

型別 簡介 特性 場景
String(字串) 二進位制安全 可以包含任何資料,比如jpg圖片或者序列化的物件,一個鍵最大能儲存512M 快取,限流,計數器,分散式鎖,分散式session
Hash(字典) 鍵值對集合,即程式語言中的Map型別 適合儲存物件,並且可以像資料庫中update一個屬性一樣只修改某一項屬性值(Memcached中需要取出整個字串反序列化成物件修改完再序列化存回去) 儲存、讀取使用者資訊、使用者主頁的訪問量,組合查詢
List(列表) 連結串列(雙向連結串列) 增刪快,提供了操作某一段元素的API 1,最新訊息排行等功能(比如朋友圈的個人動態時間線) 2,訊息佇列
Set(集合) 雜湊表實現,元素不重複 1、新增、刪除,查詢的複雜度都是O(1) 2、為集合提供了求交集、並集、差集等操作 1、好友推薦時,根據tag求交集,大於某個閾值就可以推薦2、利用唯一性,統計訪問網站的所有獨立ip 3,贊 踩 標籤
Sorted Set(有序集合) 將Set中的元素增加一個權重引數score,元素按score有序排列 1.排行榜
#Redis支援五種資料型別:
	string(字串),hash(雜湊),list(列表),set(集合)及zset(sorted set:有序集合)。
	
key
    keys * 			獲取所有的key
    select 0 		選擇第一個庫
    move key_name 1  將當前的資料庫key移動到某個資料庫,目標庫有,則不能移動
    flushall     	清除所有庫
    flushdb			清空當前庫
    randomkey    	 隨機獲取所在庫的key
    type key    	  key的型別
    
    set key1 value1 	 設定key
    get key1   			 獲取key對應的value
    mset key1 value1 key2 value2 key3 value3
    mget key1 key2 key3
    del key1   			刪除key
    exists key    		  判斷是否存在key,返回 0 1
    expire key 10   	設定某個key 10秒過期自動刪除
    pexpire key 1000 	用毫秒設定
    persist key     	刪除過期時間


#string型別,鍵值對
string 是 redis 最基本的型別,可以理解成與 Memcached 一模一樣的型別,一個 key 對應一個 value。
string 可以包含任何資料。比如jpg圖片或者序列化的物件。
string 型別是 Redis 最基本的資料型別,一個string 型別的值最大能儲存 512MB。

string
    set name cxx
    	127.0.0.1:6379> set name 'syy is ku'
    	
    get name
    getrange name 0 -1        字串分段
    	127.0.0.1:6379> getrange name 0 -1
    	
    getset name new_cxx       設定值,返回舊值
    	127.0.0.1:6379> getset name syy
		127.0.0.1:6379> get name
		
    mset key1 key2            批量設定
    mget key1 key2            批量獲取
    setnx key value           不存在就插入(0沒插入,1沒插入)
    setex key time value      過期時間(expire)
    	127.0.0.1:6379> setex name 10 syy
    setrange key index value  從index開始替換value
    	127.0.0.1:6379> set name abcdefg
		127.0.0.1:6379> setrange name 1 ha
		127.0.0.1:6379> get name
    incr age        遞增1
    incrby age 10   遞增10
    decr age        遞減1
    decrby age 10   遞減10
    incrbyfloat     增減浮點數
    	127.0.0.1:6379> incrbyfloat num 0.1
    append          追加
    	127.0.0.1:6379> append num abc
    strlen          長度
    getbit/setbit/bitcount/bitop    位操作



#hash型別,key 多個欄位 多個值
Redis hash 是一個鍵值(key=>value)對'雜湊'。
Redis hash 是一個 string 型別的 field 和 value 的對映表,hash 特別適合用於'儲存物件'。
每個 hash 可以儲存 2^32 -1 鍵值對(40多億)

hash
    hset myhash name cxx		設定單個鍵值對
    hget myhash name			獲取單個鍵值對
    hmset myhash name cxx age 25 note "i am notes"
    hmget myhash name age note   
    hgetall myhash               獲取所有的鍵值對
    hexists myhash name          是否存在
    hsetnx myhash score 100      設定不存在的
    hincrby myhash id 1          遞增
    hdel myhash name             刪除
    hkeys myhash                 只取key
    hvals myhash                 只取value
    hlen myhash                  長度

#list列表,key 多個值 索引
列表最多可儲存 2^32 - 1 元素 (4294967295, 每個列表可儲存40多億)。
列表內資料可以重複
做訊息佇列

list
    lpush mylist a b c  	左插入
    rpush mylist x y z  	右插入
    lrange mylist 0 -1  	檢視列表內所有的資料
    lpop mylist  			左彈出元素
    rpop mylist  			右彈出元素
    llen mylist  			長度
    lrem mylist count value  刪除列表內幾個value
    lindex mylist 2          指定索引的值(索引取值)
    lset mylist 2 n          索引設值
    ltrim mylist 0 4         刪除key(刪除補集的元素)
    linsert mylist before a  插入
    linsert mylist after a   插入
    rpoplpush list list2     轉移列表的資料(列表1的資料滾向列表2,排第一)
    	127.0.0.1:6379> rpoplpush mylist 0

#set集合,無序集合,key 多個無序值
Redis 的 Set 是 string 型別的無序集合,集合內元素具有'唯一性'
集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是 O(1)。
集合中最大的成員數為 2^32 - 1(4294967295, 每個集合可儲存40多億個成員)。

set
    sadd myset redis 		建立一個無序集合,新增資料Redis
    smembers myset       	檢視集合
    srem myset redis         刪除集合內資料
    sismember myset redis 	判斷元素是否在集合中
    scard set_name       	集合內資料的個數
    sdiff | sinter | sunion  差集 | 交集 | 並集
    srandmember         	 隨機獲取集合中的元素
    spop                 	從集合中隨機彈出一個元素


#zset集合,有序集合,key 多個有序值(自動排序)
Redis zset 和 set 一樣也是string型別元素的集合
不同的是每個元素都會'關聯'一個double型別的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
zset的成員是唯一的,但分數(score)卻'可以重複'。

zset
    zadd zset 1 one
    zadd zset 2 two
    zadd zset 3 three
    zincrby zset 1 one              	增長分數(加減)
    zscore zset two                 	檢視分數
    zrange zset 0 -1 withscores     	帶依據檢視排序(名值對)
    zrangebyscore zset 1 5 withscores   指定範圍的值(名值對)
    zcount zset 1 5					  指定範圍的數量
    zrangebyscore zset 10 25 withscores limit 1 2 分頁(排名'頭尾兼顧'+limit'顧頭不顧腚')
    zcard zset  					元素數量
    Zcount zset  10 20				獲得指定分數範圍內的元素'個數'
    Zrem zset one two      			  刪除一個或多個元素
    del zset						刪除集合
    Zremrangebyrank zset 0 1 		 按照排名範圍刪除元素(頭尾兼顧)
    Zremrangebyscore zset 0 1 		按照分數範圍刪除元素
    Zrevrange zset 0 -1    				   分數'最小'的元素排名為0
    Zrevrange zset 0 -1 withscores  		分數'最大'的元素排名為0
    
127.0.0.1:6379> ZCOUNT linux9 50 100
(integer) 4
127.0.0.1:6379> ZRANGEBYSCORE linux9 50 100
1) "jiwei"
2) "shengwei"
3) "banzhang"
4) "xuewei"
127.0.0.1:6379> ZRANGEBYSCORE linux9 50 100 WITHSCORES
1) "jiwei"
2) "50"
3) "shengwei"
4) "80"
5) "banzhang"
6) "90"
7) "xuewei"
8) "100"
#伺服器管理
    dump.rdb
    appendonly.aof
    //BgRewriteAof 非同步執行一個aop(appendOnly file)檔案重寫
    會建立當前一個AOF檔案體積的優化版本
    
    //BgSave 後臺非同步儲存資料到磁碟,會在當前目錄下建立檔案dump.rdb
    //save同步儲存資料到磁碟,'會阻塞主程序',別的客戶端無法連線
    
    //client kill 關閉客戶端連線
    //client list 列出所有的客戶端
    
    //給客戶端設定一個名稱
      client setname myclient1
      client getname
      
     config get port	#不配置的走預設
     //configRewrite 對redis的配置檔案進行改寫
     
rdb模式下,dump.rdb自動bgsave
save 900 1
save 300 10
save 60 10000

aof模式下,備份
appendonly yes 開啟持久化
appendfsync everysec 每秒備份一次

命令:
bgsave非同步儲存資料到磁碟(快照儲存)
lastsave返回上次成功儲存到磁碟的unix的時間戳
shutdown'同步儲存'到伺服器並關閉redis伺服器
bgrewriteaof檔案壓縮處理(命令)


 #redis事務:
     隔離性,原子性, 
     步驟:  開始事務multi,佇列命令,提交執行事務exec,取消事務discard(清空)
     		watch xx
             multi  //開啟事務
             sadd myset a b c
             sadd myset e f g
             lpush mylist aa bb cc
             lpush mylist dd ff gg    
             exec
             unwatch

#訂閱與釋出:
    訂閱頻道:subscribe chat1				#持續監控
    釋出訊息:publish chat1 "hell0 ni hao"	#在某頻道釋出訊息
    檢視頻道:pubsub channels				#檢視所有頻道
    檢視某個頻道的訂閱者數量: pubsub numsub chat1
    退訂指定頻道: unsubscribe chat1   , punsubscribe
    訂閱一組頻道: psubscribe java.*