1. 程式人生 > 實用技巧 >第四章 Redis的事務、鎖及管理命令

第四章 Redis的事務、鎖及管理命令

一.事務介紹

1.Redis的事務與關係型資料庫中的事務區別

1)在MySQL中講過的事務,具有A、C、I、D四個特性
Atomic(原子性)
所有語句作為一個單元全部成功執行或全部取消。
Consistent(一致性)
如果資料庫在事務開始時處於一致狀態,則在執行該。
事務期間將保留一致狀態。
Isolated(隔離性)
事務之間不相互影響。
Durable(永續性)
事務成功完成後,所做的所有更改都會準確地記錄在
資料庫中。所做的更改不會丟失。

2)MySQL具有MVCC(多版本併發控制)的功能,這些都是根據事務的特性來完成的。

3)redis中的事務跟關係型資料庫中的事務是一個相似的概念,但是有不同之處。關係型資料庫事務執行失敗後面的sql語句不在執行前面的操作都會回滾,而在redis中開啟一個事務時會把所有命令都放在一個佇列中,這些命令並沒有真正的執行,如果有一個命令報錯,則取消這個佇列,所有命令都不再執行。

4)redis中開啟一個事務是使用multi,相當於begin\start transaction,exec提交事務,discard取消佇列命令(非回滾操作)。

空格MySQLRedis
開啟 start transaction begin multi
語句 普通SQL 普通命令
失敗 rollback回滾 discard取消(這裡的取消不是回滾,是佇列裡的命令根本沒有執行,並不是執行了之後,再撤回)
成功 commit exec

和事務相關的命令

1)DISCARD
取消事務,放棄執行事務塊內的所有命令。
2)EXEC
執行所有事務塊內的命令。
3)MULTI
標記一個事務塊的開始。
4)UNWATCH 取消 WATCH 命令對所有 key 的監視。 5)WATCH key [key ...] 監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。

2.事務測試

#登入redis
[root@db01 ~]# redis-cli
#驗證密碼
127.0.0.1:6379> auth 123
OK
#不開啟事務直接設定key
127.0.0.1:6379> set zls "Nice"
OK
#檢視結果
127.0.0.1:6379> get zls
"Nice"

#開啟事務
127.0.0.1:6379> MULTI
OK
#設定一個key
127.0.0.1:6379> set bgx "low" QUEUED 127.0.0.1:6379> set alex "Ugly" QUEUED #開啟另一個視窗檢視結果 127.0.0.1:6379> get bgx (nil) 127.0.0.1:6379> get alex (nil) #執行exec完成事務 127.0.0.1:6379> EXEC 1) OK 2) OK #再次檢視結果 127.0.0.1:6379> get bgx "low" 127.0.0.1:6379> get alex "Ugly"

實驗結果如下:

二.Redis樂觀鎖介紹

1.樂觀鎖舉例

場景:我正在買票
Ticket -1 , money -100

而票只有1張, 如果在我multi之後,和exec之前, 票被別人買了---即ticket變成0了.
我該如何觀察這種情景,並不再提交?

1)悲觀的想法:
世界充滿危險,肯定有人和我搶, 給 ticket上鎖, 只有我能操作. [悲觀鎖]

2)樂觀的想法:
沒有那麼人和我搶,因此,我只需要注意,
--有沒有人更改ticket的值就可以了 [樂觀鎖]

3)Redis的事務中,啟用的是樂觀鎖,只負責監測key沒有被改動.

2.樂觀鎖實現

模擬買票

開啟兩個視窗實現(模擬買票)

#首先在第一個視窗設定一個key(ticket 1127.0.0.1:6379> set ticket 1
OK
#設定完票的數量之後觀察這個票
127.0.0.1:6379> WATCH ticket
OK
#開啟事務
127.0.0.1:6379> MULTI
OK
#買了票所以ticket設定為0
127.0.0.1:6379> set ticket 0
QUEUED

#然後在第二個視窗觀察票
127.0.0.1:6379> WATCH ticket
OK
#開啟事務
127.0.0.1:6379> MULTI
OK
#同樣設定ticket為0
127.0.0.1:6379> set ticket 0
QUEUED

#此時如果誰先付款,也就是執行了exec另外一個視窗就操作不了這張票了
#在第二個視窗先付款(執行exec)
127.0.0.1:6379> exec
1) OK
#然後在第一個視窗再執行exec
127.0.0.1:6379> exec
(nil)       //無,也就是說我們無法對這張票進行操作

實驗結果如下

三.Redis管理命令

1.INFO

#檢視redis相關資訊
127.0.0.1:6379> info
#服務端資訊
# Server
#版本號
redis_version:3.2.12
#redis版本控制安全hash演算法
redis_git_sha1:00000000
#redis版本控制髒資料
redis_git_dirty:0
#redis建立id
redis_build_id:3b947b91b7c31389
#執行模式:單機(如果是叢集:cluster)
redis_mode:standalone
#redis所在宿主機的作業系統
os:Linux 2.6.32-431.el6.x86_64 x86_64
#架構(64位)
arch_bits:64
#redis事件迴圈機制
multiplexing_api:epoll
#GCC的版本
gcc_version:4.4.7
#redis程序的pid
process_id:33007
#redis伺服器的隨機識別符號(用於sentinel和叢集)
run_id:46b07234cf763cab04d1b31433b94e31b68c6e26
#redis的埠
tcp_port:6379
#redis伺服器的執行時間(單位秒)
uptime_in_seconds:318283
#redis伺服器的執行時間(單位天)
uptime_in_days:3
#redis內部排程(進行關閉timeout的客戶端,刪除過期key等等)頻率,程式規定serverCron每秒執行10次
hz:10
#自增的時鐘,用於LRU管理,該時鐘100ms(hz=10,因此每1000ms/10=100ms執行一次定時任務)更新一次
lru_clock:13601047
#服務端執行命令路徑
executable:/application/redis-3.2.12/redis-server
#配置檔案路徑
config_file:/etc/redis/6379/redis.conf

#客戶端資訊
# Clients
#已連線客戶端的數量(不包括通過slave的數量)
connected_clients:2
##當前連線的客戶端當中,最長的輸出列表,用client list命令觀察omem欄位最大值
client_longest_output_list:0
#當前連線的客戶端當中,最大輸入快取,用client list命令觀察qbuf和qbuf-free兩個欄位最大值
client_biggest_input_buf:0
#正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客戶端的數量
blocked_clients:0

#記憶體資訊
# Memory
#由redis分配器分配的記憶體總量,以位元組為單位
used_memory:845336
#以人類可讀的格式返回redis分配的記憶體總量
used_memory_human:825.52K
#從作業系統的角度,返回redis已分配的記憶體總量(俗稱常駐集大小)。這個值和top命令的輸出一致
used_memory_rss:1654784
#以人類可讀方式,返回redis已分配的記憶體總量
used_memory_rss_human:1.58M
#redis的記憶體消耗峰值(以位元組為單位)
used_memory_peak:845336
#以人類可讀的格式返回redis的記憶體消耗峰值
used_memory_peak_human:825.52K
#整個系統記憶體
total_system_memory:1028517888
#以人類可讀的格式,顯示整個系統記憶體
total_system_memory_human:980.87M
#Lua指令碼儲存佔用的記憶體
used_memory_lua:37888
#以人類可讀的格式,顯示Lua指令碼儲存佔用的記憶體
used_memory_lua_human:37.00K
#Redis例項的最大記憶體配置
maxmemory:0
#以人類可讀的格式,顯示Redis例項的最大記憶體配置
maxmemory_human:0B
#當達到maxmemory時的淘汰策略
maxmemory_policy:noeviction
#記憶體分裂比例(used_memory_rss/ used_memory)
mem_fragmentation_ratio:1.96
#記憶體分配器
mem_allocator:jemalloc-4.0.3

#持久化資訊
# Persistence
#伺服器是否正在載入持久化檔案
loading:0
#離最近一次成功生成rdb檔案,寫入命令的個數,即有多少個寫入命令沒有持久化
rdb_changes_since_last_save:131
#伺服器是否正在建立rdb檔案
rdb_bgsave_in_progress:0
#最近一次rdb持久化儲存時間
rdb_last_save_time:1540009420
#最近一次rdb持久化是否成功
rdb_last_bgsave_status:ok
#最近一次成功生成rdb檔案耗時秒數
rdb_last_bgsave_time_sec:-1
#如果伺服器正在建立rdb檔案,那麼這個域記錄的就是當前的建立操作已經耗費的秒數
rdb_current_bgsave_time_sec:-1
#是否開啟了aof
aof_enabled:0
#標識aof的rewrite操作是否在進行中
aof_rewrite_in_progress:0
#rewrite任務計劃,當客戶端傳送bgrewriteaof指令,如果當前rewrite子程序正在執行,那麼將客戶端請求的bgrewriteaof變為計劃任務,待aof子程序結束後執行rewrite
aof_rewrite_scheduled:0
#最近一次aof rewrite耗費的時長
aof_last_rewrite_time_sec:-1
#如果rewrite操作正在進行,則記錄所使用的時間,單位秒
aof_current_rewrite_time_sec:-1
#上次bgrewriteaof操作的狀態
aof_last_bgrewrite_status:ok
#上次aof寫入狀態
aof_last_write_status:ok

#統計資訊
# Stats
#新建立連線個數,如果新建立連線過多,過度地建立和銷燬連線對效能有影響,說明短連線嚴重或連線池使用有問題,需調研程式碼的連線設定
total_connections_received:19
#redis處理的命令數
total_commands_processed:299
#redis當前的qps,redis內部較實時的每秒執行的命令數
instantaneous_ops_per_sec:0
#redis網路入口流量位元組數
total_net_input_bytes:10773
#redis網路出口流量位元組數
total_net_output_bytes:97146
#redis網路入口kps
instantaneous_input_kbps:0.00
#redis網路出口kps
instantaneous_output_kbps:0.00
#拒絕的連線個數,redis連線個數達到maxclients限制,拒絕新連線的個數
rejected_connections:0
#主從完全同步次數
sync_full:0
#主從完全同步成功次數
sync_partial_ok:0
#主從完全同步失敗次數
sync_partial_err:0
#執行以來過期的key的數量
expired_keys:5
#過期的比率
evicted_keys:0
#命中次數
keyspace_hits:85
#沒命中次數
keyspace_misses:17
#當前使用中的頻道數量
pubsub_channels:0
#當前使用的模式的數量
pubsub_patterns:0
#最近一次fork操作阻塞redis程序的耗時數,單位微秒
latest_fork_usec:0
#是否已經快取了到該地址的連線
migrate_cached_sockets:0

#主從複製資訊
# Replication
#角色主庫
role:master
#連線slave的個數
connected_slaves:0
#主從同步偏移量,此值如果和上面的offset相同說明主從一致沒延遲,與master_replid可被用來標識主例項複製流中的位置
master_repl_offset:0
#複製積壓緩衝區是否開啟
repl_backlog_active:0
#複製積壓緩衝大小
repl_backlog_size:1048576
#複製緩衝區裡偏移量的大小
repl_backlog_first_byte_offset:0
#此值等於 master_repl_offset - repl_backlog_first_byte_offset,該值不會超過repl_backlog_size的大小
repl_backlog_histlen:0

#CPU資訊
# CPU
#將所有redis主程序在核心態所佔用的CPU時求和累計起來
used_cpu_sys:203.44
#將所有redis主程序在使用者態所佔用的CPU時求和累計起來
used_cpu_user:114.57
#將後臺程序在核心態所佔用的CPU時求和累計起來
used_cpu_sys_children:0.00
#將後臺程序在使用者態所佔用的CPU時求和累計起來
used_cpu_user_children:0.00

#叢集資訊
# Cluster
#例項是否啟用叢集模式
cluster_enabled:0

#庫相關統計資訊
# Keyspace
#db0的key的數量,以及帶有生存期的key的數,平均存活時間
db0:keys=17,expires=0,avg_ttl=0

#單獨檢視某一個資訊(例:檢視CPU資訊)
127.0.0.1:6379> info cpu
# CPU
used_cpu_sys:203.45
used_cpu_user:114.58
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

2.client

#檢視客戶端連線資訊(有幾個會話就會看到幾條資訊)
127.0.0.1:6379> CLIENT LIST
id=19 addr=127.0.0.1:35687 fd=6 name= age=30474 idle=8962 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=info
id=21 addr=127.0.0.1:35689 fd=7 name= age=3 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
#殺掉某一個會話
127.0.0.1:6379> CLIENT KILL 127.0.0.1:35687

3.config

#重置統計狀態資訊
127.0.0.1:6379> CONFIG RESETSTAT
#檢視所有配置資訊
127.0.0.1:6379> CONFIG GET *
#檢視某個配置資訊
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "0"
#動態修改配置資訊
127.0.0.1:6379> CONFIG SET maxmemory 60G
OK
#再次檢視修改後的配置資訊
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "60000000000"

4.dbsize

#檢視當前庫內有多少個key
127.0.0.1:6379> DBSIZE
(integer) 17
#驗證key的數量
127.0.0.1:6379> KEYS *
 1) "lidao_fans"
 2) "ticket"
 3) "myhash"
 4) "teacher1"
 5) "name"
 6) "zls_fans"
 7) "bgx_fans"
 8) "mykey"
 9) "bgx"
10) "diffkey"
11) "alex"
12) "KEY"
13) "teacher"
14) "key3"
15) "unionkey"
16) "zls"
17) "wechat"

5.select

在Redis中也是有庫這個概念的,不過不同於MySQL,Redis的庫是預設的,並不是我們手動去建立的,在Redis中一共有16(0-15)個庫。在MySQL中進入某一個庫,我們需要使用use dbname,在Redis中,只需要select即可。預設情況下,我們是在0庫中進行操作,每個庫之間都是隔離的。

#在0庫中建立一個key
127.0.0.1:6379> set name zls
OK
#檢視0庫中的所有key
127.0.0.1:6379> KEYS *
1) "name"
#進1庫中
127.0.0.1:6379> SELECT 1
OK
#檢視所有key
127.0.0.1:6379[1]> KEYS *
(empty list or set)         //由此可見,每個庫之間都是隔離的

6.flushdb、flushall

#刪庫跑路專用命令(刪除所有庫)
127.0.0.1:6379> FLUSHALL
OK
#驗證一下是否真的刪庫了
127.0.0.1:6379> DBSIZE
(integer) 0
127.0.0.1:6379> KEYS *
(empty list or set)
#刪除單個庫中資料
127.0.0.1:6379> FLUSHDB
OK

7.monitor

開啟兩個視窗進行命令實時監控

#在第一個視窗開啟監控
127.0.0.1:6379> MONITOR
OK

#在第二個視窗輸入命令
127.0.0.1:6379> SELECT 2
OK
127.0.0.1:6379[2]> set name bgx
OK
127.0.0.1:6379[2]> info

#在第一個視窗會實時顯示執行的命令
127.0.0.1:6379> MONITOR
OK
1540392396.690268 [0 127.0.0.1:35689] "SELECT" "2"
1540392409.883011 [2 127.0.0.1:35689] "set" "name" "bgx"
1540392543.892889 [2 127.0.0.1:35689] "info"

實驗結果如下

8.shutdown

#關閉Redis服務
127.0.0.1:6379> SHUTDOWN
not connected>

轉自:https://www.cnblogs.com/Forever-x/p/10999497.html