Redis进阶-select 1. /xxx 切换数据库DBSIZE- 获取当前数据库中的key的个数flushdb-删除当前数据的所有keyflushall-删除所有表的所有库Re

目录

select 1.  /xxx 切换数据库

DBSIZE- 获取当前数据库中的key的个数

flushdb-删除当前数据的所有key

flushall-删除所有表的所有库

Redis应用层协议

进阶第一法

Redis事务

具体该如何进行持久化呢

关于bgsave(不影响redis处理其他客户端请求和命令)

fork

手动save/bgsave自动生成快照

AOF(append only file)

混合持久化


select 1.  /xxx 切换数据库

默认情况下redis给我们提了16个数据库(就是和mysql那种一样的数据库)

DBSIZE- 获取当前数据库中的key的个数

flushdb-删除当前数据的所有key

flushall-删除所有表的所有库

Redis应用层协议

redis客户端,使用程序操作redis——RESP(redis的应用层协议名字)

简单好去实现

快速进行解析

肉眼可读


进阶第一法

Redis事务

事务就要联想到mysql (一致性,原子性,持久性,隔离性)

mysql原子性:要么操作打包一起全部成功,要么全部失败

但是Redis的他只是一起打包,他打包的命令中有可能有的没有执行成功,所以一般都说Redis不具有原子性

redis不具有一致性:redis没有约束,没有回滚,事务执行过程中如果修改某个操作出现失败,可能会引起不一致的情况

Redis更是不具有隔离性(Redis所有的操作都是基于共享内存的,多个客户端可以同时访问和修改Redis中的数据,redis并没有直接的隔离性机制,可以考虑Redis的乐观锁机制,通过版本号,或者时间戳来去判断数据是否被其他客户端修改过)

不具备持久性->数据存硬盘中->才会持久 Redis是一个内存数据库,把数据存储在内存中的(持久化,放到内存中(为了快))   最终redis会在硬盘和内存中都存储数据,但是此处的持久化机制,和事务并没有直接关系。

Redis实现事务是引入了队列,开始事务的时候,此时客户端输入的命令,就会发给服务器并且进入这个队列中(并不是立即执行),当遇到了"执行事务"命令的时候,此时就会把队列中这些任务都按照顺序依次执行。

Redis事务为啥搞这么简单,不像是mysql这样呢?(mysql在背后付出了代价(额外开空间等等开销。时间上:也要有更大的执行开销)

什么时候用Redis事务呢?如果需要把多个操作打包进行,使用事务比较合适的秒杀场景。

典型写法

如果不加任何限制,就可能会出现"线程安全"问题

获取仓库中剩余商品的个数
if(个数>0){
下单成功
商品个数-=
}

开启事务

get count

if count>0 

decr count 

执行事务(redis收到执行事务的操作时候,才会真正执行)

假如第二个客户端(执行命令发过来,才会真正执行第二个事务中的内容,此时第一个事务执行事务命令已经运行过了,此时第二个事务get到的count就已经是第一个事务--之后的结果了)

可以用lua脚本实现redis进阶事务

开启事务:MULTI(猫体)

执行事务:EXEC

放弃当前事务:DISCARD

此时并没有执行上述指令,而是保存了上述请求,此时如果再开一个客户端,再尝试这几个key对应的数据,是没有结果的~~

dicard丢失事务操作,当开启事务,并且给服务器发送若干个命令之后,此时服务器重启~此时这个事务怎么办,此时的效果就等同于discard

WATCH监控某个key是否在事务执行前,发生了改变,等同于乐观锁

乐观锁:加锁之前,有一个心理预期,预期接下来锁冲突的概率比较低。

悲观锁:加锁之前,也有一个心理预期,接下来锁冲突的概率比较高(锁冲突:两个线程,针对一个锁加锁,一个加锁成功,一个就阻塞等待,冲突概率低和冲突概率高接下来要做的工作是不一样的。)

只有exec之后,才会真正执行事务的操作(同样CAS的ABA问题也涉及过)

具体该如何进行持久化呢

1.RDB(Redis Database)

2.AOF(Append only File)

1)定期备份:

RDB定期把我们Redis内存中数据,都写给硬盘中,生成一个"快照"

定期具体两种方式:

(1)手动触发:程序员通过redis客户端,执行特定的命令,来触发快照生成

save,执行save时,redis全力以赴进行快照生成操作,此时会阻塞redis的其他客户端命令,类似于keys *这种

bgsave,bg->bachground(后面)并不会影响Redis服务器处理其他客户端请求和命令(并发编程的场景,此处redis使用多进程,完成并发编程,完成bgsave实现

(2)自动触发(配置文件)

关于bgsave(不影响redis处理其他客户端请求和命令)

1.判断当前是否已经存在其他正在工作的子进程,比如已经有一个子进程正在执行bgsave,此时直接把bgsave返回

2.如果没有其他工作子进程,就通过fork这样的系统调用,创造出一个子进程来

fork

fork是Linux系统创造子进程的一个api(系统不同,api也不会相同),直接把当前进程,复制一份(会复制,pcb,虚拟地址空间,文件描述符表),作为子进程,安排子进程(Pob,->(复制的性能开销),文件描述表,虚拟,地址 ,空间)

否,写时拷贝,若子进程,父进程内存数据完全一样,此时并非会真拷贝,一旦某一方针对这个内存数据做出了修改,则会立即触发,物理内存上的拷贝(父进程,不会大批内存数据的变化,因此子进程的写时拷贝并不会触发多次,可保证了整体拷贝时间可控。

二进制文件->(把内存中的数据,压缩)->生成rdb镜像操作把要生成的快照数据,先保存到临时文件,当快照生成完毕之后,在删除之前的rdb文件,把新生成的rdb文件,把新生成的rdb替换成dump.rdb

rdb文件中中数据,并非你这边插入了数据,就立即更新

rdb生成的持久化文件的名字

rdb文件存储的位置

rdb触发时间:

1.手动(save bgsave)

2.自动触发条件(看配置文件)

15min至少存在一次修改

5分钟10次修改

一分钟内10000次修改

12:00:00开始插入数据

12:00:01开始redis收到了大量key变化的请求,(假如断电了,那么这个数据就会丢失,那么我们该怎么办呢? 采用AOF解决

12:01生成下一个快照文件

注意这里数值可以自动修改,但是有个基本原则:生成一次rdb快照,这个成本是一个比较高的成本,不能让这个操作执行的过于频繁。

手动save/bgsave自动生成快照

redis生成快照也可以自动触发

1.通过配置文件,save执行M时间,修改N次

2.通过shutdown命令,关闭redis服务器,也会自动触发(service redis-server restart正常关闭,kill -9 -xxx端口号,结束进程,rdb此时就会来不及复制数据,就会丢失)

3.redis进行主从复制,主节点也会自动生成rdb快照,后把rdb快照文件传输给从节点

正常重启的情况,redis会推出自动触发rdb,异常则会丢失

stat dump.rdb文件。  innode编号    linux的stat命令

Linux文件系统,组织方式(ext4),把文件系统分成三个部分

1.超级块(放的一些管理信息)

2.innode(存放innode数据结构,包含了文件各种元数据

3.block(存文件数据内容)

直接用save,不会触发子进程

bgsave:创造子进程,子进程完成持久化操作(持久化把数据写入新文件,用新文件换旧的文件)直接使用save,此时不会触发子进程&文件替换,而是,直接在当前进程中,往刚才同一个文件中写入数据。

4.通过自动配置生成rdb快照

手动改坏rdb,一定通过kill进程方式,重新启动redis服务器(这样才会真正损坏,不要损坏,问题还是蛮麻烦的,前后改还没准能跑,但是一旦中间位置被毁就g)

假如通过service redis-server restart重启,就会在redis服务器退出后重新生成rdb快照,把改坏的文件替换掉了

redis-check-rdb检查工具和redis服务器在5.0版本是同一可执行程序,可运行时,假如不同选项,从而使用不同的功能。

运行时候以rdb为参数,此时就是检查工具来运行,并不会真正启动redis服务器

AOF使用文本来组织数据,进行一系列字符串切分

老版本的rdb,放到新版本不一定能够识别

遍历旧的redis有key,取数据后,放到新redis服务器即可

RDB最大问题就是不能够实时化保存数据,两次快照之间,实时数据kennel随着重启而去丢失,这时也就引入另一个AOF

AOF(append only file)

类似于mysql的binlog会把用户的每个操作,都记录到文件中

当aof生效的时候,rdb就会关闭,启动的时候就不在读取rdb文件内容了

aof默认是关闭状态

上面表示开始,还是关闭aof操作(当前是关闭),下面这个是aof的文件名,和rdb文件的所在位置一样

AOF是一个文本文件,每次操作都会把记录到文本文件中,通过一些特殊符号作为分隔符。

那么我们思考一个问题:他这东西又写内存,又写硬盘,又写内存,会快吗?

实际上是没有影响的!并没有影响到redis处理请求的速度

1.AOF机制并非是直接让工作线程把数据写入硬盘,而是先写入一个内存中的缓存区,积累一波之后,再统一写入硬盘(大大降低了,写硬盘的次数)

2.硬盘上读写数据,顺序读写的速度是比较快的(还是比较内存要慢很多)随机访问则速度比较慢~~

AOF是每次把新的操作写入原有文件的末尾,属于顺序写入~。

刷新频率越高,性能影响越大,同时数据的可靠性越高。

刷频率越低,性能越小,数据可靠性越低。

AOF文件持续增长,体积会越来越大,会影响到,redis下次启动时间,redis启动的时候读取aof文件内容

aof中是记录了中间的过程,但是实际上redis重新启动的时候,只是关注结果,因此redis存在一个机制,就是针对aof文件进行整理,可以剔除其中冗余操作,并且合并一些操作,达到aof文件瘦身的效果。

同样也是分为手动触发和自动触发

手动触发:调用bgrewriteaof命令
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数自动触发时机

auto-aof-rewrite-min-size:表示触发重写时AOF的最小文件大小,默认是64MB

auto-aof-rewrite-percentage:代表当前AOF占用大小相比较上次重写的时候增加的比例

父进程负责接收请求,子进程负责针对aof文件进行重写

注意!!!重写的时候,不关心aof文件原来都有啥~,只是关心内存中最终的数据状态!!

子进程只需要把内存中当前数据,获取出来,以AOF格式写入到一个新的AOF文件中

(内存中的数据的状态,就已经是把AOF文件整理后的模样了)

此处的子进程写数据过程,十分类似于RDB生成的一个镜像快照,只不过RDB这里是按照二进制方式来生成的,AOF重写,则是按照AOF要求的文本格式,来生成的,都是为了把当前内存中的数据状态记录到文件中。

子进程在写新的AOF文件的同时,父进程仍在不停的接收客户端的新的请求,父进程还是会写把这些请求产生的AOF数据写入缓存区,再刷新到原有的AOF文件里面。

在创建子进程的一瞬间,子进程就继承了当前父进程的内存状态,因此,子进程的内存数据是父进程fork之前的状态,fork之后,新来的请求,对内存的修改,子进程是不知道的

此时父进程这里,有准备了一个aof_rewrite_buf缓冲区~专门放fork之后收到的数据。

子进程这边,把aof数据写完之后,会通过信号通知父进程,父进程再把aof_rewrite_buf缓冲区的内容也写入到新AOF文件里~(子进程fork之前,父进程fork之后,两个写完之后,就可以用新的aof文件代替旧的aof文件里。)

如果,在执行bgrewriteaof时候,当前redis已经正在进行aof重写了,会怎么样呢?

此次,不会再次aof重写,直接返回了。

如果,在执行bgwirteaof的时候,发现redis在生成rdb文件的快照,会咋样呢?

此时,aof重写操作就会等待,等待rdb快照生成完毕之后,再进行执行aof重写

rdb对于fork之后的新数据,就置之不理了,而aof对于fork之后的新数据,采取了aof_rewrite_buf缓冲区的方式来处理

rdb本身的设计理念,就是来定期备份的

只要是定期备份,就难以最新的数据保持一致

aof的理念就是实时备份。哪个好,具体看场景

父进程fork完毕之后,就已经让子进程写新的aof文件了,并且随着时间的推移,子进程就很快写完了新的文件,要让新的aof文件代替旧的,父进程此时还在继续写这个即将消亡的旧的aof是否有意义呢?(考虑断电情况,子进程内存数据会丢失,新的aof文件内容还不完整,如果父进程不坚持写旧的aof文件,重启没办法保证数据完整性)

混合持久化

redis引用了混合持久化的方式,结合了rdb和aof的特点,按照aof的方式,每一个请求/操作,都记录文件,在触发aof重写之后,就会把当前内存的状态按照rdb二进制格式写入到新的aof文件中,后续再进行到操作,仍然是按照aof文本的方式追加到文件后面

下面这个yes表示开启混合持久化

当redis同时存在aof和rdb文件时候,以aof为主

  • 30
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗哥不是甜妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值