目录
一.事务
事务是逻辑上对数据的的一组操作,这组操作要么一次全部成功,或者这组操作全部失败;是不可分割的一个工作单位
1.事务四大特性(ACID)
- 原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败
- 一致性(Consistency):是事务对数据完整性约束的遵循。这些约束可能包括主键约束、外键约束或是一些用户自定义约束。事务执行的前后都是合法的数据状态,不会违背任何的数据完整性
- 隔离性(Isolation):事务与事务之间互不打扰
- 持久性(Durability):一个事务一旦成功提交,它对数据库的改变必须是永久的,即便是数据库发生故障也应该不回对其产生任何影响。
2.redis的事务
redis是弱事务型的数据库,并不具备ACD的全部特性
redis具备隔离性:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制
3.事务命令
muti #开启事务
...
...
...
exec #提交到数据库执行
discard #取消事务
4. 特殊情况
a)命令入队失败,直接自动discard退出这个事务
这个在命令在执行调用之前会发生错误。例如,这个命令可能有语法错误(错误的参数数量,错误的命令名)
处理方案:语法错误则自动执行discard
b)命令语法没错,但类型操作有误,在命令输入后不会报错,但事务执行调用之后失败,无法进行事务回滚
当我们执行了一个由于错误的value的key操作会出现该现象(例如对着String类型的value施行了List命令操作)
处理方案:发生在EXEC之后的是没有特殊方式去处理的:即使某些命令在事务中失败,其他命令都将会被执行
二.python操作事务
python操作redis需要借助流水线(客户端技术)
1.流水线(pipeline)
批量执行redis命令,减少通信io
原理:效仿redis的事务,客户端将多个命令打包,一次通信发给redis,可明显降低redis服务的请求数
注意:
1,此为客户端技术
2,如果一组命令中,一个命令需要上一个命令的执行结果才可以执行,则无法使用该技术
python实现
import redis
pool = redis.ConnectionPool(host ='127.0.0.1',post=6379,db=0 )
r= redis.Redis(connection_pool=pool)
pipe = r.pipeline()
pipe.set('aa',1)
pipe.incr('aa')
pipe.incrby('aa',2)
pipe.execute()#返回所有结果
2.操作事务
with r.pipline(transaction=true) as pipe:
pipe.multi()
#...
#...
values = pipe.execute()
3.watch乐观锁
事务过程中,可对指定key监听,命令提交时,若被监听的key发生改变,则提交失败返回nil,这是解决资源竞争的一种方式
使用方式
watch key
#监听key
redis.WatchError
#python返回的报错内容
三.数据持久化-RDB
1.特点
- 保存真实的数据
- 将服务器包含的所有数据库数据以二进制文件的形式保存到硬盘里面(全量备份)
- 默认文件名:/var/lib/redis/dump.rdb
文件名及目录可在配置文件中修改【/etc/redis/redis.conf】
dir /var/lib/redis #表示rdb文件存放路径
dbfilename dump.rdb#文件名
2.触发方式
- 终端执行SAVE:1.redis会阻塞 2.若已存在文件,则会代替旧文件
- 终端执行BGSAVE:1.后台fork()子进程进行SAVE 2.完成之后记录在var/log/redis-server.log中
- 设置配置文件
save 900 1 save 300 10 save 60 10000 #save 距离上一次创建RDB文件的时间 数据库的修改次数 #1、只要三个条件中的任意一个被满足时,服务器就会自动执行BGSAVE #2、每次创建RDB文件之后,服务器为实现自动持久化而设置的时间计数器和次数计数器就会被清零,并重新开#始计数,所以多个保存条件的效果不会叠加
- 数据库正常停止也会触发RDB,异常无法触发
3.注意
1、创建RDB文件需要将服务器所有的数据库的数据都保存起来,这是一个非常消耗资源和时间的操作,所以服务器需要隔一段时间才创建一个新的RDB文件,也就是说,创建RDB文件不能执行的过于频繁,否则会严重影响服务器的性能
2、若停止redis并且删除RDB文件则可能丢失数据
四.数据持久化-AOF
1.基础概念
存储的是命令,而不是真实数据
默认不开启,开启方式(修改配置文件)
1、/etc/redis/redis.conf
appendonly yes#把no改为yes
appendfilename“appendonly.aof"
2、重启服务
sudo/etc/init.d/redis-server restart
2.执行原理
每当有修改数据库的命令被执行时,在AOF文件中写入
因为AOF文件里面存储了服务器执行过的所有数据库修改的命令,所以给定一个AOF文件,服务器只要重新执行一遍AOF文件里面包含的所有命令,就可以达到还原数据库的目的
用户可以根据自己的需要对AOF持久化进行调整,让Redis在遭遇意外停机时不丢失任何数据,或者只丢失一秒钟的数据,这比RDB持久化丢失的数据要少的多
3.特殊说明
虽然服务器执行一个修改数据库的命令,就会把执行的命令写入到AOF文件,但这并不意味着AOF文件持久化不会丢失任何数据,在目前常见的操作系统中,执行系统调用write函数,将一些内容写入到某个文件里面时,为了提高效率,系统通常不会直接将内容写入硬盘里面,而是将内容放入一个内存缓存区(buffer)里面,等到缓冲区被填满时才将存储在缓冲区里面的内容真正写入到硬盘里
1、AOF持久化:当一条命令真正的被写入到硬盘里面时,这条命令才不会因为停机而意外丢失
2、AOF持久化在遭遇停机时丢失命令的数量,取决于命令被写入到硬盘的时间
3、越早将命令写入到硬盘,发生意外停机时丢失的数据就越少,反之亦然
相关配置:
#打开配置文件:/etc/redis/redis.conf,找到相关策略如下
1、alwarys
服务器每写入一条命令,就将缓冲区里面的命令写入到硬盘里面,服务器就算意外停机 也不会丢失任何已经成功执行的命令数据
2、everysec(#默认)
服务器每一秒将缓冲区里面的命令写入到硬盘里面,这种模式下,服务器即使遭遇意外停机,最多只丢失1秒的数据
3、no
服务器不主动将命令写入硬盘,由操作系统决定何时将缓冲区里面的命令写入到硬盘里面,丢失命令数量不确定
4.AOF重写
由于AOF文件会产生很多冗余命令,为了让AOF文件的大小控制在合理范围,避免胡乱增长,redis提供了AOF重写功能,通过这个功能,服务器可以产生一个新的AOF文件
新的AOF文件记录的数据库数据和原由的AOF文件记录的数据库数据完全一样
--新的AOF文件会使用尽可能少的命令来记录数据库数据,因此新的AOF文件
的提及通常会小很多
—-AOF重写期间,服务器不会被阻塞,可以正常处理客户端发送的命令请求
使用:
可以在终端
BGREWRITEAOF
或者修改配置文件让服务器自动执行BGREWRITEAOF命令
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 解释
只有当AOF文件的增量大于100%时才进行重写,也就是大一倍的时候才触发
#第一次重写新增:64M
#第二次重写新增:128M
#第三次重写新增:256M(新增128M)
五.主从复制
高可用是系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。
目标:消除基础架构中的单点故障。
redis单进程单线程模式,如果redis进程挂掉,相关依赖的服务就难以正常服务
redis的高可用方案-主从搭建+哨兵
1.基础概念
- 一个Redis服务可以有多个该服务的复制品,这个Redis服务成为master,其他复制品成为slaves
- master会一直将自己的数据更新同步给slaves,保持主从同步
- 只有master可以执行写命令,slave只能执行读命令
- 作用:分担了读的压力(高并发);提高可用性
- 原理:从服务器执行客户端发送的读命令,客户端可以连接slaves执行读请求,来降低master的读压力
2.实现方式
linux命令行
reids-server --port --slaveof master-ip master-port --masterauth master password
redis-cli -p port
#通过info中的Replication查看当前redis信息
redis终端
redis-server --port number
slaveof ip port
#成为从
slaveof no one
#成为主
配置文件加载
#每个redis服务,都有1个和他对应的配置文件
# 两个redis服务
1、6379(默认端口) ->/etc/redis/redis.conf
2、6300 -> 启动服务的目录
#修改配置文件(一般都是cp redis.conf文件,这里就简便配置直接写)
vim redis_6300.conf
#redis_6300.conf
slaveof 127.0.0.1 6379
port 6300
# 启动redis服务
redis-server redis_6300.conf
#客户端连接测试
redis-cli-p 6300
六.哨兵
1.基础概念
Sentinel会不断检查Master和Slaves是否正常
每一个Sentinel可以监控任意多个Master和该Master下的Slaves原理:正如其名,哨兵进程定期与redis主从进行通信,当哨兵认为redis主‘阵亡'后【通信无返回】,自动将切换工作完成
2.安装与配置
sudo apt install redis-sentinel
#下载
sudo service redis-sentinel stop
#这里关闭默认开启的哨兵,自己配置一个
vim sentinel.conf
#sentinel.conf
port 26379
sentinel monitor name ip port number
#name:集群名称 ip,port:master参数 number:阈值票数
sentinel auth-pass name password
#主从密码必须相同
sentinel down-after-milliseconds name time(ms)
#多少秒失联判断宕机
#启动sentinel:redis-sentinel 启动哨兵文件的路径
3.python操作哨兵
from redis.sentinel import Sentinel
#生成哨兵连接
sentinel = sentinel([('localhost', 26379)],socket_timeout=0.1)
#初始化master连接
master = sentinel.master_for('tedu', socket_timeout=0.1,db=1)
slave = sentinel.slave_for('tedu',socket_timeout=0.1, db=1)
#使用redis相关命令
master.set('mymaster', 'yes')
print(slave.get('mymaster'))