一.事务介绍

二.Redis乐观锁介绍

三.Redis管理命令

一.事务介绍

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取消队列命令(非回滚操作)。

MySQL Redis
开启 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 被其他命令所改动,那么事务将被打断。

事务测试

  1. #登录redis
  2. [root@db01 ~]# redis-cli
  3. #验证密码
  4. 127.0.0.1:6379> auth 123
  5. OK
  6. #不开启事务直接设置key
  7. 127.0.0.1:6379> set zls "Nice"
  8. OK
  9. #查看结果
  10. 127.0.0.1:6379> get zls
  11. "Nice"
  12.  
  13. #开启事务
  14. 127.0.0.1:6379> MULTI
  15. OK
  16. #设置一个key
  17. 127.0.0.1:6379> set bgx "low"
  18. QUEUED
  19. 127.0.0.1:6379> set alex "Ugly"
  20. QUEUED
  21. #开启另一个窗口查看结果
  22. 127.0.0.1:6379> get bgx
  23. (nil)
  24. 127.0.0.1:6379> get alex
  25. (nil)
  26.  
  27. #执行exec完成事务
  28. 127.0.0.1:6379> EXEC
  29. 1) OK
  30. 2) OK
  31.  
  32. #再次查看结果
  33. 127.0.0.1:6379> get bgx
  34. "low"
  35. 127.0.0.1:6379> get alex
  36. "Ugly"

实验结果如下:

二.Redis乐观锁介绍


乐观锁举例

场景:我正在买票
Ticket -1 , money -100

而票只有1张, 如果在我multi之后,和exec之前, 票被别人买了---即ticket变成0了.
我该如何观察这种情景,并不再提交?

1)悲观的想法:
世界充满危险,肯定有人和我抢, 给 ticket上锁, 只有我能操作. [悲观锁]

2)乐观的想法:
没有那么人和我抢,因此,我只需要注意,
--有没有人更改ticket的值就可以了 [乐观锁]

3)Redis的事务中,启用的是乐观锁,只负责监测key没有被改动.


乐观锁实现

模拟买票

开启两个窗口实现(模拟买票)

  1. #首先在第一个窗口设置一个key(ticket 1)
  2. 127.0.0.1:6379> set ticket 1
  3. OK
  4. #设置完票的数量之后观察这个票
  5. 127.0.0.1:6379> WATCH ticket
  6. OK
  7. #开启事务
  8. 127.0.0.1:6379> MULTI
  9. OK
  10. #买了票所以ticket设置为0
  11. 127.0.0.1:6379> set ticket 0
  12. QUEUED
  13.  
  14. #然后在第二个窗口观察票
  15. 127.0.0.1:6379> WATCH ticket
  16. OK
  17. #开启事务
  18. 127.0.0.1:6379> MULTI
  19. OK
  20. #同样设置ticket为0
  21. 127.0.0.1:6379> set ticket 0
  22. QUEUED
  23.  
  24. #此时如果谁先付款,也就是执行了exec另外一个窗口就操作不了这张票了
  25. #在第二个窗口先付款(执行exec)
  26. 127.0.0.1:6379> exec
  27. 1) OK
  28. #然后在第一个窗口再执行exec
  29. 127.0.0.1:6379> exec
  30. (nil) //无,也就是说我们无法对这张票进行操作

实验结果如下:

三.Redis管理命令

INFO

  1. #查看redis相关信息
  2. 127.0.0.1:6379> info
  3. #服务端信息
  4. # Server
  5. #版本号
  6. redis_version:3.2.12
  7. #redis版本控制安全hash算法
  8. redis_git_sha1:00000000
  9. #redis版本控制脏数据
  10. redis_git_dirty:0
  11. #redis建立id
  12. redis_build_id:3b947b91b7c31389
  13. #运行模式:单机(如果是集群:cluster)
  14. redis_mode:standalone
  15. #redis所在宿主机的操作系统
  16. os:Linux 2.6.32-431.el6.x86_64 x86_64
  17. #架构(64位)
  18. arch_bits:64
  19. #redis事件循环机制
  20. multiplexing_api:epoll
  21. #GCC的版本
  22. gcc_version:4.4.7
  23. #redis进程的pid
  24. process_id:33007
  25. #redis服务器的随机标识符(用于sentinel和集群)
  26. run_id:46b07234cf763cab04d1b31433b94e31b68c6e26
  27. #redis的端口
  28. tcp_port:6379
  29. #redis服务器的运行时间(单位秒)
  30. uptime_in_seconds:318283
  31. #redis服务器的运行时间(单位天)
  32. uptime_in_days:3
  33. #redis内部调度(进行关闭timeout的客户端,删除过期key等等)频率,程序规定serverCron每秒运行10次
  34. hz:10
  35. #自增的时钟,用于LRU管理,该时钟100ms(hz=10,因此每1000ms/10=100ms执行一次定时任务)更新一次
  36. lru_clock:13601047
  37. #服务端运行命令路径
  38. executable:/application/redis-3.2.12/redis-server
  39. #配置文件路径
  40. config_file:/etc/redis/6379/redis.conf
  41.  
  42. #客户端信息
  43. # Clients
  44. #已连接客户端的数量(不包括通过slave的数量)
  45. connected_clients:2
  46. ##当前连接的客户端当中,最长的输出列表,用client list命令观察omem字段最大值
  47. client_longest_output_list:0
  48. #当前连接的客户端当中,最大输入缓存,用client list命令观察qbuf和qbuf-free两个字段最大值
  49. client_biggest_input_buf:0
  50. #正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量
  51. blocked_clients:0
  52.  
  53. #内存信息
  54. # Memory
  55. #由redis分配器分配的内存总量,以字节为单位
  56. used_memory:845336
  57. #以人类可读的格式返回redis分配的内存总量
  58. used_memory_human:825.52K
  59. #从操作系统的角度,返回redis已分配的内存总量(俗称常驻集大小)。这个值和top命令的输出一致
  60. used_memory_rss:1654784
  61. #以人类可读方式,返回redis已分配的内存总量
  62. used_memory_rss_human:1.58M
  63. #redis的内存消耗峰值(以字节为单位)
  64. used_memory_peak:845336
  65. #以人类可读的格式返回redis的内存消耗峰值
  66. used_memory_peak_human:825.52K
  67. #整个系统内存
  68. total_system_memory:1028517888
  69. #以人类可读的格式,显示整个系统内存
  70. total_system_memory_human:980.87M
  71. #Lua脚本存储占用的内存
  72. used_memory_lua:37888
  73. #以人类可读的格式,显示Lua脚本存储占用的内存
  74. used_memory_lua_human:37.00K
  75. #Redis实例的最大内存配置
  76. maxmemory:0
  77. #以人类可读的格式,显示Redis实例的最大内存配置
  78. maxmemory_human:0B
  79. #当达到maxmemory时的淘汰策略
  80. maxmemory_policy:noeviction
  81. #内存分裂比例(used_memory_rss/ used_memory)
  82. mem_fragmentation_ratio:1.96
  83. #内存分配器
  84. mem_allocator:jemalloc-4.0.3
  85.  
  86. #持久化信息
  87. # Persistence
  88. #服务器是否正在载入持久化文件
  89. loading:0
  90. #离最近一次成功生成rdb文件,写入命令的个数,即有多少个写入命令没有持久化
  91. rdb_changes_since_last_save:131
  92. #服务器是否正在创建rdb文件
  93. rdb_bgsave_in_progress:0
  94. #最近一次rdb持久化保存时间
  95. rdb_last_save_time:1540009420
  96. #最近一次rdb持久化是否成功
  97. rdb_last_bgsave_status:ok
  98. #最近一次成功生成rdb文件耗时秒数
  99. rdb_last_bgsave_time_sec:-1
  100. #如果服务器正在创建rdb文件,那么这个域记录的就是当前的创建操作已经耗费的秒数
  101. rdb_current_bgsave_time_sec:-1
  102. #是否开启了aof
  103. aof_enabled:0
  104. #标识aof的rewrite操作是否在进行中
  105. aof_rewrite_in_progress:0
  106. #rewrite任务计划,当客户端发送bgrewriteaof指令,如果当前rewrite子进程正在执行,那么将客户端请求的bgrewriteaof变为计划任务,待aof子进程结束后执行rewrite
  107. aof_rewrite_scheduled:0
  108. #最近一次aof rewrite耗费的时长
  109. aof_last_rewrite_time_sec:-1
  110. #如果rewrite操作正在进行,则记录所使用的时间,单位秒
  111. aof_current_rewrite_time_sec:-1
  112. #上次bgrewriteaof操作的状态
  113. aof_last_bgrewrite_status:ok
  114. #上次aof写入状态
  115. aof_last_write_status:ok
  116.  
  117. #统计信息
  118. # Stats
  119. #新创建连接个数,如果新创建连接过多,过度地创建和销毁连接对性能有影响,说明短连接严重或连接池使用有问题,需调研代码的连接设置
  120. total_connections_received:19
  121. #redis处理的命令数
  122. total_commands_processed:299
  123. #redis当前的qps,redis内部较实时的每秒执行的命令数
  124. instantaneous_ops_per_sec:0
  125. #redis网络入口流量字节数
  126. total_net_input_bytes:10773
  127. #redis网络出口流量字节数
  128. total_net_output_bytes:97146
  129. #redis网络入口kps
  130. instantaneous_input_kbps:0.00
  131. #redis网络出口kps
  132. instantaneous_output_kbps:0.00
  133. #拒绝的连接个数,redis连接个数达到maxclients限制,拒绝新连接的个数
  134. rejected_connections:0
  135. #主从完全同步次数
  136. sync_full:0
  137. #主从完全同步成功次数
  138. sync_partial_ok:0
  139. #主从完全同步失败次数
  140. sync_partial_err:0
  141. #运行以来过期的key的数量
  142. expired_keys:5
  143. #过期的比率
  144. evicted_keys:0
  145. #命中次数
  146. keyspace_hits:85
  147. #没命中次数
  148. keyspace_misses:17
  149. #当前使用中的频道数量
  150. pubsub_channels:0
  151. #当前使用的模式的数量
  152. pubsub_patterns:0
  153. #最近一次fork操作阻塞redis进程的耗时数,单位微秒
  154. latest_fork_usec:0
  155. #是否已经缓存了到该地址的连接
  156. migrate_cached_sockets:0
  157.  
  158. #主从复制信息
  159. # Replication
  160. #角色主库
  161. role:master
  162. #连接slave的个数
  163. connected_slaves:0
  164. #主从同步偏移量,此值如果和上面的offset相同说明主从一致没延迟,与master_replid可被用来标识主实例复制流中的位置
  165. master_repl_offset:0
  166. #复制积压缓冲区是否开启
  167. repl_backlog_active:0
  168. #复制积压缓冲大小
  169. repl_backlog_size:1048576
  170. #复制缓冲区里偏移量的大小
  171. repl_backlog_first_byte_offset:0
  172. #此值等于 master_repl_offset - repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小
  173. repl_backlog_histlen:0
  174.  
  175. #CPU信息
  176. # CPU
  177. #将所有redis主进程在内核态所占用的CPU时求和累计起来
  178. used_cpu_sys:203.44
  179. #将所有redis主进程在用户态所占用的CPU时求和累计起来
  180. used_cpu_user:114.57
  181. #将后台进程在内核态所占用的CPU时求和累计起来
  182. used_cpu_sys_children:0.00
  183. #将后台进程在用户态所占用的CPU时求和累计起来
  184. used_cpu_user_children:0.00
  185.  
  186. #集群信息
  187. # Cluster
  188. #实例是否启用集群模式
  189. cluster_enabled:0
  190.  
  191. #库相关统计信息
  192. # Keyspace
  193. #db0的key的数量,以及带有生存期的key的数,平均存活时间
  194. db0:keys=17,expires=0,avg_ttl=0
  195.  
  196. #单独查看某一个信息(例:查看CPU信息)
  197. 127.0.0.1:6379> info cpu
  198. # CPU
  199. used_cpu_sys:203.45
  200. used_cpu_user:114.58
  201. used_cpu_sys_children:0.00
  202. used_cpu_user_children:0.00

client

  1. #查看客户端连接信息(有几个会话就会看到几条信息)
  2. 127.0.0.1:6379> CLIENT LIST
  3. 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
  4. 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
  5. #杀掉某一个会话
  6. 127.0.0.1:6379> CLIENT KILL 127.0.0.1:35687

config

  1. 重置统计状态信息
  2. 127.0.0.1:6379> CONFIG RESETSTAT
  3. #查看所有配置信息
  4. 127.0.0.1:6379> CONFIG GET *
  5. #查看某个配置信息
  6. 127.0.0.1:6379> CONFIG GET maxmemory
  7. 1) "maxmemory"
  8. 2) ""
  9. #动态修改配置信息
  10. 127.0.0.1:6379> CONFIG SET maxmemory 60G
  11. OK
  12. #再次查看修改后的配置信息
  13. 127.0.0.1:6379> CONFIG GET maxmemory
  14. 1) "maxmemory"
  15. 2) ""

dbsize

  1. #查看当前库内有多少个key
  2. 127.0.0.1:6379> DBSIZE
  3. (integer) 17
  4. #验证key的数量
  5. 127.0.0.1:6379> KEYS *
  6. 1) "lidao_fans"
  7. 2) "ticket"
  8. 3) "myhash"
  9. 4) "teacher1"
  10. 5) "name"
  11. 6) "zls_fans"
  12. 7) "bgx_fans"
  13. 8) "mykey"
  14. 9) "bgx"
  15. 10) "diffkey"
  16. 11) "alex"
  17. 12) "KEY"
  18. 13) "teacher"
  19. 14) "key3"
  20. 15) "unionkey"
  21. 16) "zls"
  22. 17) "wechat"

select

在Redis中也是有库这个概念的,不过不同于MySQL,Redis的库是默认的,并不是我们手动去创建的,在Redis中一共有16(0-15)个库。在MySQL中进入某一个库,我们需要使用use dbname,在Redis中,只需要select即可。默认情况下,我们是在0库中进行操作,每个库之间都是隔离的。

  1. #在0库中创建一个key
  2. 127.0.0.1:6379> set name zls
  3. OK
  4. #查看0库中的所有key
  5. 127.0.0.1:6379> KEYS *
  6. 1) "name"
  7. #进1库中
  8. 127.0.0.1:6379> SELECT 1
  9. OK
  10. #查看所有key
  11. 127.0.0.1:6379[1]> KEYS *
  12. (empty list or set) //由此可见,每个库之间都是隔离的

flushdb、flushall

  1. #删库跑路专用命令(删除所有库)
  2. 127.0.0.1:6379> FLUSHALL
  3. OK
  4. #验证一下是否真的删库了
  5. 127.0.0.1:6379> DBSIZE
  6. (integer) 0
  7. 127.0.0.1:6379> KEYS *
  8. (empty list or set)
  9. #删除单个库中数据
  10. 127.0.0.1:6379> FLUSHDB
  11. OK

shutdown

  1. #关闭Redis服务
  2. 127.0.0.1:6379> SHUTDOWN
  3. not connected>

第四章· Redis的事务、锁及管理命令的更多相关文章

  1. 记一个Redis分布式事务锁

    package com.mall.common; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory. ...

  2. 【JAVA今法修真】 第四章 redis特性 击穿雪崩!

    感谢这段时间大家的支持,关注我的微信号:南橘ryc ,回复云小霄,就可以获取到最新的福利靓照一张,还等什么,赶快来加入我们吧~ "明日便是决赛了,咋只会用法器没练过法术呢.". 选 ...

  3. 《JavaScript高级程序设计》——第四章 变量、作用域和内存管理

    JavaScript变量可以用保存两种类型的值:基本类型值和引用类型值.基本类型的值源自以下基本类型数据:Undefined.Null.Boolean.Number和String. 从一个变量向另一个 ...

  4. Redis之(三)管理命令

    4.1键管理 通过学习五种数据类型的操作命令,可以发现,Redis对每种数据的处理之前,都要先指定该数据的key,然后再指定对该数据进行何种操作. Redis中的key有点类似于Java中的变量名,起 ...

  5. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  6. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

  7. redis事务中的WATCH命令和基于CAS的乐观锁

    转自:http://blog.sina.com.cn/s/blog_ae8441630101cgy3.html 在Redis的事务中,WATCH命令可用于提供CAS(check-and-set)功能. ...

  8. 【分布式缓存系列】Redis实现分布式锁的正确姿势

    一.前言 在我们日常工作中,除了Spring和Mybatis外,用到最多无外乎分布式缓存框架——Redis.但是很多工作很多年的朋友对Redis还处于一个最基础的使用和认识.所以我就像把自己对分布式缓 ...

  9. 【Redis】事务 (超详细)

    一.概述 二.相关命令列表 2.1 MULTI 2.2 EXEC 2.3 DISCARD 2.4 WATCH key [key ...] 2.5 UNWATCH 三.命令示例 3.1 事务被正常执行 ...

随机推荐

  1. 常用的Arrays类和二维数组以及二分法的介绍

    ---恢复内容开始--- 1.Array类 Array中包含了许多数组的常用操作,较为常见的有: (1)快速输出 import java.util.Arrays; public class Test{ ...

  2. 18、实现strStr()

    18.实现strStr() 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 ( ...

  3. nth-child(n)和nth-of-type(n)的区别

    1.官方解释: p:nth-child(2)     选择属于其父元素的第二个子元素的每个 <p> 元素. p:nth-of-type(2) 选择属于其父元素第二个 <p> 元 ...

  4. Centos7 系统下搭建.NET Core2.0+Nginx+Supervisor+Mysql环境

    好记性不如烂笔头! 一.简介 一直以来,微软只对自家平台提供.NET支持,这样等于让这个“理论上”可以跨平台的框架在Linux和macOS上的支持只能由第三方项目提供(比如Mono .NET).直到微 ...

  5. Registrator中文文档

    目录 快速入门 概述 准备 运行Registrator 运行Redis 下一步 运行参考 运行Registrator Docker选项 Registrator选项 Consul ACL令牌 注册URI ...

  6. win10系统下安装MySQLdb和pymysql

      (1)使用的是Python3.6,想要使用MySQLdb, 需要先在https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient中下载相应版本的包 ...

  7. Android apk安装时出现“解析软件包错误”

    有时候在安装apk的时候会出现解析软件包出错 (Android studio)解决方法如下: 关闭Instant Run功能: File-Settings-...看下图: 将红色框内的勾取消. 如果还 ...

  8. C#设置电脑时间帮助类

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...

  9. FocusListener焦点监听器

    [FocusListener焦点监听器] public class Demo extends JFrame { public Demo(){ setDefaultCloseOperation(Wind ...

  10. 第五周课后作业——热门软件创新分析+附加题1&附加题3

    鉴于我们寝室都热衷于手游,所以本次热门软件创新分析我就来分析一下几款热门的抽卡型手游.   阴阳师(后文简称YYS)——剧情画风唯美,配音引人入胜 作为网易公司研发的一款3D日式和风回合制游戏,YYS ...