当前位置: 首页 > news >正文

MySQL笔记15

一、 Redis 事务管理

1. Redis 的事务特性

  Redis事务并非严格意义上的事务,只是用于批量执行多个命令的打包脚本。

  单个Redis命令执行是原子性的,但Redis事务没有维持原子性的机制,中间某条指令失败不会导致前面指令回滚,也不影响后续指令执行。

  Redis事务是单独的隔离操作,事务内所有命令会序列化、按顺序执行,可防止其他命令插队。

2.事务执行过程

(1)三阶段

一个事务从开始到执行会经历以下三个阶段:

  开始事务

  命令入队

  执行事务

(2)基本指令

指令功能
multi组装并启动一个事务
exec执行一个事务
discard取消一个事务
watch监视指定key,若这些key在事务执行前被修改,事务将被取消执行

(3)过程

执行逻辑:从输入 multi 命令开始,后续输入的命令会依次进入命令队列但不执行;直到输入 exec 后, Redis 会依次执行命令队列中的命令。组队过程中可通过 discard 放弃组队。

示例:

组建事务(先定义一个 key 为 user_id , value 为1。然后输出其值和开始事务, incr 为自增1运算,它的返回值 QUEUED 表示这些命令并没有执行,只是进入执行队列,可以多增几次来检测。最后输入 exec 开始执行事务队列的命令,可以看到值的增加):

注意:

  上例演示了一个完整的事务过程,所有的指令在 exec 之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦收到 exec 指令,才开执行整个事务队列,执行完毕后一次性返回所有指令的运行结果。因为 Redis 的单线程特性,不用担心自己在执行队列的时候被其它指令打搅,可以保证他们能得到的有顺序的执行。

取消事务(执行 multi 开启事务后,入队了三次 incr 命令,随后执行 discard ,即可成功取消该事务。最后查询结果为1说明事务中的命令未被执行):

注意:discard 命令必须在 multi 开启的事务组队阶段使用,即要在 multi 之后、 exec 之前使用,且不带任何参数。

3.事务的错误处理

(1)情况1

  若 Redis 事务组队阶段( multi 之后、 exec 之前)某条命令出现报告错误,执行 exec 后整个命令队列会被取消,事务中所有命令都不会执行。

示例:

下图中 Redis 事务因组队阶段命令语法错误( inc 拼写错误),所以执行 exec 时整个事务被放弃, group_id 值未改变。

注意:在 Redis 中,事务取消后,它的命令队列会被清空,这个事务实例就不存在了。之后可以继续使用同名的命令来组建新的事务,因为 Redis 的事务是基于 “每次 multi 开启一个新的事务上下文” 的机制,只要重新执行 multi ,就可以开启一个新的事务。

(2)情况2

  在事务执行阶段若某条命令报错,仅该报错命令不执行,其他命令仍会执行且不会回滚。

示例:

  开启事务后入队两次 incr group_id 和一次 incr name ,但因字符串无法自增,所以执行 exec 时, incr name 报错,而 incr group_id 正常执行,最终 group_id 变为3。

4.事务的冲突问题

(1)事务场景

有一账户余额为 10000 元,现在三个请求:

  第一个请求想给金额减 8000 元

  第二个请求想给金额减 5000 元

  第三个请求想给金额减 1000 元

如果没有事务,可能会发生如下情况:

最后金额会变为负值。

(2)悲观锁(Pessimistic Lock)

概念:悲观锁认为每次拿数据时别人都会修改,因此拿数据时会上锁,导致其他人操作该数据时会被阻塞,直到拿到锁。

应用:传统关系型数据库(如行锁、表锁、读锁、写锁等)多采用这种锁机制,操作前先上锁。

(3)乐观锁(Optimistic Lock)

概念:乐观锁持乐观态度,拿数据时认为别人不会修改,所以不上锁;更新时会判断期间数据是否被他人修改,可通过版本号等机制实现。

应用:适用于多读的应用类型,能提高吞吐量。Redis 利用 check-and-set (检查并设置)机制实现事务,就是基于乐观锁的思路。

(4)watch 监听

功能:在执行 multi 前,通过 watch key1 [key2] 可监视一个或多个key。若事务执行前这些 key 被其他命令改动,事务会被打断。

示例:

客户端 A (开始监听后,开启事务并入队 decrby  plan  2000 命令):

客户端 B (在另一个客户端修改了 plan 的值。):

客户端 A (此时返回原来的客户端执行 exec 后发现,因 plan 已被客户端 B 修改,所以事务提交失败,返回 nil 。):

注意:Redis 禁止在 multi 和 exec 之间执行 watch 指令,且必须在 multi 之前盯住关键变量,否则会出错。

(5)unwatch 取消监听

功能:用于取消 watch 命令对所有 key 的监视。

注意:若在执行 watch 后,先执行了 exec 命令(执行事务)或 discard 命令(取消事务),则无需再执行 unwatch ,因为这两个命令会自动取消 watch 对 key 的监视。

5. Redis 的事务三特性

  单独的隔离操作:事务内所有命令会序列化、按顺序执行,执行过程中不会被其他客户端的命令请求打断。

  没有隔离级别的概念:事务队列里的命令在提交( exec )前不会实际执行。

  不保证原子性:事务中若某条命令执行失败,后续命令仍会执行,不会回滚。

二、数据持久化

1.概念

  Redis 数据持久化是为防止 Redis 因内存存储数据在宕机时丢失,将内存中的数据库数据保存到磁盘的机制。其有两种持久化方式:RDB(Redis DataBase)和AOF(Append Of File)

2.RDB

(1)作用

  在指定时间间隔内,将内存中所有数据集进行全量快照(Snapshot)写入磁盘。恢复时直接将快照文件读入内存,类似拍照记录某一瞬间的完整数据状态。数据通过 rdbSave 从内存写入磁盘的RDB文件,再通过 rdbLoad 从RDB文件加载回内存。

(2)原理

  创建子进程进行持久化,先将数据写入临时文件,持久化完成后替换上次的持久化文件;主进程不进行 IO 操作,保证了高性能。适用于大规模数据恢复且对完整性要求不高的场景,但缺点是最后一次持久化后的数据可能丢失。

(3)Fork

Redis 的 Fork 机制基于写时复制技术(COW)实现快照持久化(在执行快照的同时,正常处理写操作) :

Fork(多进程) 的作用:Redis 在持久化时会调用 glibc 的函数 fork 产生一个子进程(所有数据,包括:变量、环境变量、程序计数器等数值都和原进程一致),快照持久化完全交给子进程来处理,父进程继续处理客户端请求

主进程需要修改数据时的处理:

  gsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。

  bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。

  此时,如果主线程对这些数据也都是读操作(例如下图中的键值对 K1 ),那么,主线程和 bgsave 子进程相互不影响。

  但是,如果主线程要修改一块数据(例如下图中的键值对  K3 ),那么,这块数据就会被复制一份,生成该数据的副本。

  然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

(4)快照运行过程

当 Redis 需要保存 dump.rdb 文件时, 服务器执行 bgsave 命令后则执行以下操作:

  Redis 调用 fork() ,产生一个子进程,此时同时拥有父进程和子进程。

  父进程继续处理 client 请求,子进程负责将内存内容写入到临时文件。由于 os 的写时复制机制,父子进程会共享相同的物理页面,当父进程处理写请求时, os 会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是 fork 时刻整个数据库的一个快照。

  当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

(5)相关配置

配置文件名:根据 redis.conf 中的配置, 快照将被写入 dbfilename 指定的文件中(默认是 dump.rdb 文件)。

  配置文件路径: 快照将保存在 dir 选项指定的路径上,我们可以修改为指定目录。

注意:由于此路径是一个相对路径,它会根据命令执行的所在目录来生成 dump.rdb 文件,因此建议修改指定目录为固定位置,如:/usr/local/redis/data

save:

作用:配置备份规则

格式:save 秒数 修改次数

示例:

先进入配置文件中 vim /etc/redis/redis.conf ,然后找到数据持久化处修改 save (由于文件内容过多,可以输入搜索功能命令来进行定位,如默认配置一般为下图,在 vim 的普通模式下输入 /save 3600 即能定位成功)

把持久化的策略修改为 save 30 5 (表示 30 秒内写入 5 条数据就产生一次快照,也就是生成 rdb 文件 ):

 修改好后,保存并重启 redis 服务,然后打开客户端,执行如下命令:

最后然后查看 dump.rdb 文件的大小,发现文件快照已经产生了。

注意:

Redis的持久化命令有两种:

  save :手动保存,会阻塞所有操作,不建议使用。

  bgsave :自动保存,Redis在后台异步进行快照操作,同时可响应客户端请求。

其他:

  stop-writes-on-bgsave-error:当 Redis 无法写入磁盘的话,直接关掉 Redis 的写操作,推荐配置为 yes。

  rdbcompression:对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,Redis 会采用 LZF 算法进行压缩。 如果不想消耗CPU来进行压缩,可以设置为关闭此功能。推荐配置为 yes。

  rdbchecksum:在存储快照后,还可以让 Redis 使用 CRC64 算法来进行数据校验,检查数据完整性。 但这样做会增加大约 10% 的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。推荐配置为 yes。

(6)备份

示例:

先清库:

再重新添加如下数据:

备份 dump.rdb 文件,且关闭 Redis 服务,最后将原来的 dump.rdb 文件删除:

(7)恢复

接着上一步备份操作:

先将 dump.rdb.back 文件名修改为 dump.rdb (并重启Redis服务):

再连接客户端,执行如下命令来查看(原来删除的内容就恢复了):

(8)优势

  适合大规模数据恢复

  对数据完整性和一致性要求不高更适合使用

  节省磁盘空间

  基于二进制存储的,恢复速度快

(9)劣势

  Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑

  虽然Redis在fork时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能。

  在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。

3.AOF

(1)作用

  以日志形式增量保存每个写操作(读操作不记录),仅追加文件、不可改写,Redis 启动时读取该文件重新构建数据。Redis 重启时会按 AOF 文件中写指令的顺序执行,完成数据恢复。

默认配置中AOF未开启,需手动开启才能使用。

AOF 通过将写命令追加到文件末尾记录数据变化,执行文件中所有写命令即可恢复数据集。

(2)实现 AOF 日志

  数据库常见的写前日志(WAL)是在实际写数据前记录修改到日志文件,实现“日志先行”;而 Redis 的 AOF 日志是写后日志,即 Redis 先执行命令将数据写入内存,之后再记录日志。

注意:

  日志先行方式宕机后可通过日志恢复数据;而 AOF 采用后写日志方式,若宕机可能丢失已写入内存但未记录日志的数据。

  传统数据库的日志,例如 redo log(重做日志),记录的是修改后的数据,而 AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。

  以 Redis 收到 “set k1 v1” 命令后记录的日志为例,看看 AOF 日志的内容。

其中:

  “ *2 ” 表示当前命令有两个部分,每部分都是由 “ $+数字 ” 开头,后面紧跟着具体的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。

  例如,*2 表示有两个部分,6表示6个字节,也就是下边的 “SELECT” 命令,1 表示 1 个字节,也就是下边的 “0” 命令,合起来就是 SELECT 0,选择 0 库,下边的指令同理。

总结:

  为了避免额外的检查开销,Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错。

  而写后日志这种方式,就是先让系统执行命令,只有命令能执行成功,才会被记录到日志中,否则,系统就会直接向客户端报错。

  Redis 使用写后日志这一方式的一大好处是,可以避免出现记录错误命令的情况。除此之外,AOF 是在命令执行后才记录日志,所以不会阻塞当前的写操作。

(3)原理

  客户端的请求写命令会被 append 追加到 AOF 缓冲区内。

  AOF 缓冲区根据 AOF 持久化策略 [always,everysec,no] 将操作 sync 同步到磁盘的 AOF 文件中。

  AOF 文件大小超过重写策略或手动重写时,会对 AOF 文件 rewrite 重写,压缩 AOF 文件容量。

  Redis 服务重启时,会重新 load 加载 AOF 文件中的写操作达到数据恢复的目的。

(4)使用方法

进入配置文件里,把 no 改为 yes 即可开启 AOF 持久化:

通过 appendfilename 指定日志文件名字(默认为appendonly.aof):

通过 appendfsync 指定日志记录频率:

appendfsync 的配置选项:

选项同步频率
always每个redis写命令都要同步写入硬盘,优点是当发生系统崩溃时数据丢失减至最少,缺点是这种策略会产生大量的I/O操作,会严重降低服务器的性能。
everysec以每秒一次的频率对 AOF 文件进行同步,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器几乎没有任何影响。
no由操作系统决定何时同步,会增加系统崩溃时数据丢失的数量。

示例:

确保有 /appendonlydir 目录后,停止 Redis 服务,然后再重新开启 Redis 服务后,就可以在 / 目录下会生成多个以 appendonly 开头的文件:

文件从左到右为:

  基本文件,是一个快照,表示文件创建时数据集的完整状态

  增量文件, 包含应用于前一个文件之后的数据集的额外命令

  清单文件,用于跟踪文件及其创建和应用的顺序

登录添加一些 key ,再退出查看增量内容:

(5)Rewrite(重写)

概念:

  AOF 采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制。当 AOF 文件的大小超过所设定的阈值时,Redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。

  以使用命令 bgrewriteaof 实现,该操作相当于“瘦身”, 在重写的时候,是根据这个键值对当前的最新状态,为它生成对应的写入命令。这样一来,一个键值对在重写日志中只用一条命令就行了,而且,在日志恢复时,只用执行这条命令,就可以直接完成这个键值对的写入了

原理:

  AOF 文件持续增长而过大时,会 fork 出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,转换成一条条的操作指令,再序列化到一个新的 AOF 文件中。

  参数 no-appendfsync-on-rewrite=yes ,表示不写入 AOF 文件只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。 这样做可以降低数据安全性,提高性能。

  如果参数 no-appendfsync-on-rewrite=no , 则还是会把数据往磁盘里刷,但是遇到重写操作,可能会发生阻塞。这样做可以数据安全,但是性能降低。

触发机制:

  Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。

  重写虽然可以节约大量磁盘空间,减少恢复时间。但是每次重写还是有一定的负担的,因此设定Redis要满足一定条件才会进行重写。

  参数 auto-aof-rewrite-percentage :设置重写的基准值,文件达到100%时开始重写(文件是原来重写后文件的2倍时触发)

  参数 auto-aof-rewrite-min-size :设置重写的基准值,最小文件64MB。达到这个值开始重写。

(6)重写流程

  Redis 执行 fork() ,现在同时拥有父进程和子进程,子进程开始将新 AOF 文件的内容写入到临时文件。

  对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾:这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。

  当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。

  现在 Redis 使用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾,如图:

(7)优势

  备份机制更稳健,丢失数据概率更低。

  可读的日志文本,通过操作AOF稳健,可以处理误操作。

(8)劣势

  比起RDB占用更多的磁盘空间。

  恢复备份速度要慢。

  每次读写都同步的话,有一定的性能压力。

  存在个别Bug,造成恢复不能。

(9)选择

那么,在开发中是选择 RDB 还是选择 AOF 来持久化呢?官网建议如下:

  官方推荐使用 RDB 与 AOF 混合式持久化。

  若对数据安全性要求不高,则推荐使用纯 RDB 持久化方式。

  不推荐使用纯 AOF 持久化方式。

  若 Redis 仅用于缓存,则无需使用任何持久化技术。

http://www.dtcms.com/a/509563.html

相关文章:

  • 做养生网站怎么样小程序制作永久免费
  • 怎么查自己专业是否符合一建系统优化是什么意思
  • 网站建设推广语言鄂尔多斯建设局网站
  • 手机网站制作步骤我为什么不建议年轻人做运营
  • 宜春招聘网站开发区招工徐州市城乡建设局官方网站
  • 通配符对称冲突检测工具
  • Linux小课堂: 数据处理核心命令之grep、sort、wc、uniq 与 cut 的深度解析
  • 深圳建筑设计平台网站wordpress wp posts
  • 北京住房和城乡建设官方网站色彩搭配比较好的网站
  • 找到网站后台地址如何做自己网站
  • 有没有人做网站大学做html个人网站素材
  • 嘉兴五县两区网站建设局机关网站建设
  • 江苏省交通建设厅门户网站wordpress如何修改首页文件模板
  • 如何建立一个网站详细步骤通辽住房和城乡建设厅网站
  • 网站设计需要多少钱小程序开发教程 下载
  • 公司无网站无平台怎么做外贸2021最火关键词
  • 手机网站的静态页面官网站站
  • 蒙古网站后缀国内知名设计工作室
  • 单页网站怎么制作昆明企业网站建设公司
  • 建设银行兰州分行网站百度小程序开发平台
  • 朝阳网站建设 慈云寺厦门易尔通网站建设好吗
  • 网站 备案 哪个省建设培训中心网站
  • 成都大型网站建设公司iis网站属性在哪
  • 中国站长查询域名备案西安有哪些做网站的公司好
  • 东莞定制网站建设jsp网站部署怎么做
  • 百度推广太原网站建设阿里云服务器添加网站
  • 2016网站优化今天深圳新增确诊最新消息
  • 驾校官方网站 模板wordpress手动装插件
  • 怎样直接输入网址打开网站ps做网站标签
  • 甘肃肃第八建设集团网站1wordpress关联adsense