2)MySQL具備MVCC(多版本併發控制)的功能,這些都是根據事務的特性來完成的。git
3)redis中的事務跟關係型數據庫中的事務是一個類似的概念,可是有不一樣之處。關係型數據庫事務執行失敗後面的sql語句不在執行前面的操做都會回滾,而在redis中開啓一個事務時會把全部命令都放在一個隊列中,這些命令並無真正的執行,若是有一個命令報錯,則取消這個隊列,全部命令都再也不執行。redis
4)redis中開啓一個事務是使用multi,至關於begin\start transaction,exec提交事務,discard取消隊列命令(非回滾操做)。算法
空格 | MySQL | Redis |
---|---|---|
開啓 | start transaction begin | multi |
語句 | 普通SQL | 普通命令 |
失敗 | rollback回滾 | discard取消(這裏的取消不是回滾,是隊列裏的命令根本沒有執行,並非執行了以後,再撤回) |
成功 | commit | exec |
和事務相關的命令sql
1)DISCARD 取消事務,放棄執行事務塊內的全部命令。 2)EXEC 執行全部事務塊內的命令。 3)MULTI 標記一個事務塊的開始。 4)UNWATCH 取消 WATCH 命令對全部 key 的監視。 5)WATCH key [key ...] 監視一個(或多個) key ,若是在事務執行以前這個(或這些) key 被其餘命令所改動,那麼事務將被打斷。
#登陸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"
實驗結果以下:
數據庫
場景:我正在買票
Ticket -1 , money -100api
而票只有1張, 若是在我multi以後,和exec以前, 票被別人買了---即ticket變成0了.
我該如何觀察這種情景,並再也不提交?緩存
1)悲觀的想法:
世界充滿危險,確定有人和我搶, 給 ticket上鎖, 只有我能操做. [悲觀鎖]安全
2)樂觀的想法:
沒有那麼人和我搶,所以,我只須要注意,
--有沒有人更改ticket的值就能夠了 [樂觀鎖]服務器
3)Redis的事務中,啓用的是樂觀鎖,只負責監測key沒有被改動.網絡
模擬買票
開啓兩個窗口實現(模擬買票)
#首先在第一個窗口設置一個key(ticket 1) 127.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相關信息 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
#查看客戶端鏈接信息(有幾個會話就會看到幾條信息) 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
#重置統計狀態信息 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"
#查看當前庫內有多少個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"
在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) //因而可知,每一個庫之間都是隔離的
#刪庫跑路專用命令(刪除全部庫) 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
開啓兩個窗口進行命令實時監控
#在第一個窗口開啓監控 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"
實驗結果以下

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