事務處理
redis對事務的支援目前還比較簡單。redis隻能保證一個client發起的事務中的指令可以連續的執行,而中間不會插入其他client的指令。當一個client在一個連接配接中發出multi指令時,這個連接配接會進入一個事務上下文,該連接配接後續的指令不會立即執行,而是先放到一個隊列中,當執行exec指令時,redis會順序的執行隊列中的所有指令。
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379> multi
ok
//表示事務開始
127.0.0.1:6379> set age 10
queued
//表示放入隊列
127.0.0.1:6379> set age 20
//表示這兩個都放入隊列中了
127.0.0.1:6379> exec
//分别分别傳回兩條指令的結果
1) ok
2) ok
"20"
127.0.0.1:6379>
a:取消一個事務,使用discard
ok
127.0.0.1:6379> set age 30
queued
127.0.0.1:6379> set age 40
127.0.0.1:6379> discard
可以發現這次2個set
age指令都沒被執行。discard指令其實就是清空事務的指令隊列并退出事務上下文,也就是我們常說的事務復原。
b.樂觀鎖:大多數是基于資料版本(version)的記錄機制實作的。即為資料增加一個版本辨別,在基于資料庫表的版本解決方案中,一般是通過資料庫表添加一個“version”字段來實作讀取出資料時,将此版本号一同讀出,之後更新時,對此版本号加1。此時,将送出資料的版本号與資料庫表對應記錄的目前版本号進行比對,如果送出的資料版本号大于資料庫目前版本号,則予以更新,否則認為是過期資料。
redis樂觀鎖執行個體:假設一個age的key,我們開2個session來對age進行指派操作,我們來看一下結果如何。
watch指令會監視給定的key,當exec時候如果監視的key從調用watch後發生過變化,則整個事務會失敗。也可以調用watch多次監視多個key。這樣就可以對指定的key加樂觀鎖了,注意watch的key是對整個連接配接有效的,事務也一樣。如果連接配接斷開,監視和事務都會被自動清除。當然了exec,discard,unwatch指令都會清除連接配接中的所有監視。
127.0.0.1:6379> get name
127.0.0.1:6379> set name toto
127.0.0.1:6379> incr age
127.0.0.1:6379> incr name
127.0.0.1:6379> exec
1) (integer) 21
//可以看到事務并沒有復原,執行了一條,後面一條失敗
2) (error) err value is not an integer or out of range
"21"
"toto"
從這個例子中可以看到,age由于是個數字,那麼它可以有自增運算,但是name是個字元串,無法對其進行自增運算,是以會報錯,如果按傳統關系型資料庫的思路來講,整個事務都會復原,但是我們看到redis卻是将可以執行的指令送出了,是以這個現象對于習慣關系型資料庫操作的朋友來說是很别扭的,這一點也是redis今天需要改進的地方。
持久化機制
redis是一個支援持久化的記憶體資料庫,也就是說redis需要經常講記憶體中的資料同步到硬碟來保證持久化。redis支援兩種持久化方式:
snapshotting(快照)也是預設方式。(也就是說把資料做一個備份)
append-only file(縮寫aof)的方式。(将寫和更改删除等操作放到檔案中)。
快照是預設的持久化方式。這種方式是将記憶體中資料以快照的方式寫入到二進制檔案中。預設的檔案名為dump.rdb。可以通過配置自動做快照持久化的方式。我們可以配置redis在n秒内如果超過m個key被修改就自動做快照。
save 900 1 #900秒内如果超過1個key被修改,則發起快照儲存
save 300 10 #300秒内容如超過10個key被修改,則發起快照儲存
save 60 10000
rdb所在位置:
預設開啟的配置是:
aof方式:
由于快照方式是在一定間隔時間做一次的,是以如果redis意外down掉的話,就會丢失最後一次快照後的所有修改。
aof比快照方式更好的持久性,是由于在使用aof時,redis會将每一個收到的寫指令都通過write函數追加到檔案中,當redis重新開機時會通過重新執行檔案中儲存的寫指令來在記憶體中重建整個資料庫的内容。
當然由于os會在核心中緩存write做的修改,是以可能不是立即寫到磁盤上。這樣aof方式的持久化也還是有可能丢失部分修改。
可以通過配置檔案告訴redis我們想要通過fsync函數強制os寫入到磁盤的時機。
appendonly yes
//啟動aof持久化方式
# appendfsync always
//收到寫指令就立即寫入磁盤,最慢,但是保證完全的持久化。(表示每次寫都會往檔案中寫一次)
appendfsync everysec
//每秒鐘寫入磁盤一次,在性能和持久化方面做了很好的折中。(表示每秒都會執行一次)
#appendfsync no
//完全依賴os,性能最好,持久化沒保證
要修改的配置檔案是:vim /usr/local/redis/etc/redis.conf
appendonly的預設參數是no,我們可以給它改成yes
修改同步方式:
重新啟動伺服器:/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
測試運作
[toto@localhost ~]$ /usr/local/redis/bin/redis-cli
127.0.0.1:6379> set name toto1
(error) noauth authentication required.
127.0.0.1:6379> auth toto
127.0.0.1:6379> exit
[toto@localhost ~]$ ll
總用量 60
drwxrwxr-x. 2 toto toto 4096 10月 16 19:09
1016
-rw-r--r--. 1 toto toto
57 2月
15 15:59 appendonly.aof
-rw-rw-r--. 1 toto toto
38 2月
15 15:56 dump.rdb
drwxr-xr-x. 3 root root 4096 10月 13 16:34
mysql
drwxrwxr-x. 3 toto toto 4096 2月
6 17:24 redis
drwxrwxr-x. 2 toto toto 4096 1月
31 19:58 server
drwxrwxr-x. 3 toto toto 4096 10月 16 19:02
shell
drwxr-xr-x. 2 toto toto 4096 10月 16 08:58
公共的
模闆
視訊
圖檔
文檔
下載下傳
音樂
drwxr-xr-x. 2 toto toto 4096 10月 16 10:07
桌面
[toto@localhost ~]$ ls
1016
appendonly.aof dump.rdb
mysql redis server
shell 公共的
模闆
視訊
圖檔
文檔
下載下傳
音樂
[toto@localhost ~]$
cat appendonly.aof
*2
$6
select
$1
*3
$3
set
$4
name
$5
toto1
toto2
由上可以知道aof檔案中存的是寫指令。
釋出及訂閱消息
釋出訂閱(pub/sub)是一種消息通信模式,主要的目的是解除消息釋出者和消息訂閱者之間的耦合,redis作為一個pub/sub的server,在訂閱者和釋出者之間起到了消息路由的功能。訂閱者可以通過subscribe和psubscribe指令向redis
server訂閱自己感興趣的消息類型,redis将資訊類型稱為通道(channel).當釋出者通過publish指令向redis
server發送特定類型的資訊時,訂閱資訊類型的全部client都會收到此消息。
實驗步驟:
打開三個用戶端:
分别使用:/usr/local/redis/bin/redis-cli -a toto登入用戶端
在第一個用戶端輸入:subscribe tv1
通過這種方式監聽tv1頻道
在第二個用戶端輸入:subscribe tv1 tv2
通過這種方式監聽tv1,tv2頻道
在第三個用戶端通過public指令釋出消息,輸入:以下指令:
這樣,在第一個用戶端和第二個用戶端中會監聽到第三個用戶端釋出的消息,最後的輸出如下:
用戶端一的消息如下:
用戶端二的消息如下:
應用:做消息系統和聊天系統
虛拟記憶體的使用:
redis的虛拟記憶體與作業系統的虛拟記憶體記憶體不是一回事兒,但是思路和目的都是相同的。就是暫時把不經常通路的資料從記憶體交換到磁盤中,進而騰出寶貴的記憶體空間用于其他需要通路的資料。尤其是對于redis這樣的記憶體資料庫,記憶體總是不夠用的。除了可以将資料分割到多個redis
server外。另外能夠提高資料庫容量的辦法就是使用虛拟記憶體把那些不經常通路的資料交換到磁盤上。
下面是虛拟記憶體的配置情況:
vm-enabled yes
#開啟vm功能
vm-swap-file /tmp/redis.swap
#交換出來的value儲存的檔案路徑
vm-max-memory 1000000
#redis使用的最大記憶體上限
vm-page-size 32
#每個頁面的大小32位元組
vm-pages 134217728
#最多使用多少頁面
vm-max-threads 4
#用于執行value對象換入的工作線程數量
注意:自己在2.配置的時候上面的參數不可以配置。