事务
- .
基础概念
- 场景: 小明账户100元, 小红账户50元
- 需求: 小明转账50给小红
- 数据库语句: <1. 小明账户-50元><2. 小红账户+50元>
- 问题: 如果执行1句时, 数据库进程就死掉了…
- 事务是逻辑上数据库的一组操作, 这组操作要么一次成功, 或者这组操作全部失败, 是不可分割的一个工作单位
- 事务的四大特性:
- 原子性
- 一致性
- 隔离性
- 持久性
事务的四大特性(ACID)
- 原子性
事务中所有操作是不可分割的原子单位, 事务中所有擦欧洲哦要么全部执行成功, 要么全部执行失败 - 一致性
是事务对数据完整性约束的遵循, 这些约束可能包括主键约束, 外键约束或是一些用户自定义约束. 事务执行的前后都是合法的数据状态, 不会违背任何的数据完整性. - 隔离性
事务与事务之间互不打扰 - 持久性
一个事务一旦成功提交, 他对数据库的改变必须是永久的, 几遍是数据库发生故障也应该不回对其产生任何影响.
redis的事务
- redis是弱事务的数据库, 并不具备ACID的全部特性
- redis具备隔离性: 事务中的所有命令会被去序列化, 按顺序执行, 在执行的过程中不会被其他客户端发送来的命令打算
- 不保证原子性: redis中的一个事务中如果存在执行失败, 那么其他命令会被执行, 没有回滚机制.
事务命令
- MULTI # 开启事务 mysql begin
- 命令1 #执行命令
- 命令2 …
- EXEC # 提交到数据库执行 mysql commit
- DISCARD # 取消事务 mysql ‘rollback’
事务特殊情况- 命令语法错误
- 命令入队失败, 直接自动discard退出这个事务
- 这个命令在执行调用之前会发生错误. 例如, 这个命令可能有语法错误(错误的参数数量. 错误的命令名)
- 处理方案: 语法错误则自动执行discard
- `` 事务特殊情况 - 类型操作错误(续)
pipeline 流水线
- 批量执行redis命令. 减少通信io
- 原理: 消防redis的事务, 客户端将多个命令打包, 一次通信发给redis, 可明显降低redis服务的请求数
- 注意:
- 此为客户端技术
- 如果一组命令中, 一个命令需要上一个命令的执行结果才可以执行, 则无法使用该技术
- python 操作事务, 需要依赖, 流水线技术
with r.pipeline(transcation=True) as pipe:
pipe.multi()
pipe.incr('books')
pipe.incr('books')
values = pipe.execture()
watch - 乐观锁
- 事务过程中, 可对指定的key进行监听, 命令提交时, 若被监听key对应的值未被修改, 事务方可提交成功, 否则失败
- 解决资源竞争的一种方式
- python 操作watch
- 信用卡提升额度, 每次提升额度, 当前余额都变为原来的两倍
数据持久化-RDB
- what - 将数据从掉电易丢失的内存放到永久存储的设备上
- why - 因为所有的数据都在内存上, 所以必须得持久化
- redis提供两种持久化方案
- RDB默认开启
- ADF
RDB
- 保存真实的数据
- 将服务器包含的所有数据库数据以二进制文件的形式保存到硬盘里面
- 默认文件名:
var/lib/redis/dump.rdb
- 文件名 及目录可在配置文件中修改 [
/etc/redis/redis.conf
] - 263行: dir
/var/lib/redis
# 表示rdb文件存放路径 - 253行: dbfilename dump.rdb # 文件名
- 文件名 及目录可在配置文件中修改 [
- 触发rdb持久化 - redis终端
- 方式1 redis终端中使用
SAVE
或者BGSAVE
命令
- 方式1 redis终端中使用
- SAVE
127.0.0.1:6379> SAVE OK
- 特点
- 执行SAVE命令过程中, redis服务器将阻塞, 无法处理客户端的命令请求, 在SAVE命令执行完毕后, 服务器才会重新开始处理客户端发送的命令请求, 在SAVE命令执行完毕后, 服务器才会重新开始处理客户端发送的命令请求
- 如果RDB文件已经存在, 那么服务器将自动用心的RDB文件替代的RDB文件
- 特点
- BGSAVE
127.0.0.1:6379> BGSAVE Background saving started
- 执行过程如下
- 客户端 发送 BGSAVE 给服务器
- 服务器马上返回
Background saving started
给客户端 - 服务器
fork()
子进程做这件事 - 服务器继续提供服务
- 子进程创建完RDB文件后再告知Redis服务器
- 执行过程如下
- 对比
- save比BGSAVE快, 因为需要创建子进程, 消耗额外的内存
- 说明: 可以通过查看日志文件来查看redis的持久化过程
- logfile位置:
var/log/redis/redis-server.log
- redis配置文件默认
- 218行: save 900 1
- 219行: save 300 10
表示如果距离上一次创建RDB文件已经过去300秒, 并且服务器的所有数据库总共已经发生了不少于10次修改, 那么自动执行BGSAVE命令
- 220 行: save 60 10000
- 只要三个条件中的任意一个被满足时, 服务器就会自动执行BGSAVE
- 每次创建RDB文件之后, 服务器为实现自动持久化而设置的时间计数器和次数计数器就会被清零, 并重新开始计数, 所以多个保存条件的效果不会叠加
- 触发rdb持久化 - redis关闭
- redis在正常关闭时. 也会执行保存rdb操作
注意:
异常关闭, 无法自动触发rdb操作
- 特殊说明
- 创建RDB文件需要将服务器所有的数据库的数据都保存起来, 这是一个非常消耗资源和时间的操作, 所以服务器需要隔一段时间才创建一个新的RDB文件, 也就是说, 创建RDB文件不能执行的过于频繁, 否则会严重影响服务器的性能
- 可能丢失数据
AOF
-
基础概念
- 存储的是命令, 而不是真实数据
- 默认不开启
开启方式(修改配置文件)- /etc/redis/redis.conf
672行 : appendonly yes # 把no
改成yes
676行: appendfilename “appendonly.aof” - 重启服务
sudo /etc/init.d/redis-server restart
- /etc/redis/redis.conf
-
执行原理
- 每当有修改数据库的命令被执行时,
- 因为AOF文件里面存储了服务器执行过的所有数据库修改的命令. 所以给定一个AOF文件, 服务器只要重新执行一遍AOF文件里面包含的所有命令, 就可以达到还原数据库的目的
用户可以根据自己的需要对AOF持久化进行调整, 让redis在遭遇意外停机时不丢失任何数据, 或者之丢失一秒钟的数据, 这比RDB持久化丢失的数据要少的多
3 .特殊说明虽然服务器执行一个修改数据库的命令, 就会把执行的命令写人到AOF文件, 但这并不意味这AOF文件持久化不会丢失任何数据, 在目前常见的操作系统中, 执行系统调用write函数, 将一些内容写入到某个文件里面时, 为了提高效率, 系统通常不会直接将内容写入到硬盘里面, 而是将内容放入一个内存缓存区(buffer)里面, 等到缓冲区被填满时才将存储在缓冲区里面的内容真正写入到硬盘里面
-
相关配置
- 701行: always
服务器每写入一条命令, 就将缓冲区里面的命令写入到硬盘里面, 服务器就算意外停机, 也不会丢失任何已经成功执行的命令数据 - 702行: everysec (#默认)
服务器每一秒将缓冲区里面的命令写入到硬盘里面, 这种模式下,服务器及时遭遇意外停机, 最多只丢失一秒的数据 - 703行: no
服务器不主动将命令写入磁盘, 由操作系统决定何时将缓冲区里面的命令写入到硬盘里面, 丢失命令数量不确定.
- 701行: always
-
AOF重写
思考:AOF问阿金中是否会昌盛很多的冗余命令?
为了让AOF文件的大小控制在合理范围, 避免胡乱增长, redis提供了AOF重写功能 ,通过这个功能, 服务器可以产生一个新的AOF文件
— 新的AOF文件记录的数据库数据和原由的AOF文案记录的数据完全一样
— 新的AOF问阿金会使用尽可能少的命令来记录数据库数据, 因此新的AOF文件的提及通常会少很多
— AOF重写时间, 服务器不会阻塞, 可以正常处理客户端发送的命令请求
RDB持久化解 | AOF持久化 |
---|---|
全量备份, 一次保存整个数据库 | 增量备份, 一次保存一个修改数据库的命令 |
保存的间隔较长 | 保存的间隔默认为一秒钟 |
数据还原速度快 | 数据还原速度一般, 冗余命令长, 还原速度慢 |
执行SAVE命令时会阻塞服务器, 但手动或自动触发的BGSAVE不会阻塞服务器 | 无论是平时还是进行AOF重写时, 都不会阻塞服务器 |
主从复制
- 基本概念
高可用 - 是系统架构设计中必须考虑的因素之一, 它通常是指, 通过设计减少系统不能提供服务的时间.
目标:消除基础架构中的单点故障.redis单进程单线程模式, 如果redis进程挂掉, 相关依赖的服务就难以正常服务
- redis高可用方案-主从搭建+ 哨兵
- 主从复制
- 一个redis服务可以有多个该服务的复制品, 这个redis服务成为master, 其他复制成为slaves
- master会一直将自己的数据更新同步给slaves, 保持主从同步
- master可以执行
读写
命令, slave只能执行读
命令
作用: 分担了读的压力(高并发); 提高可用性
原理: 从服务器执行客户端发送的读命令, 客户端可以连接slaves执行读请求, 来降低master的读压力
…