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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
简介: Redis进阶-select 1. /xxx 切换数据库DBSIZE- 获取当前数据库中的key的个数flushdb-删除当前数据的所有keyflushall-删除所有表的所有库Re

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为主


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
|
6天前
|
存储 NoSQL Redis
【Azure Developer】一个复制Redis Key到另一个Redis服务的工具(redis_copy_net8)
介绍一个简单的工具,用于将Redis数据从一个redis端点复制到另一个redis端点,基于原始存储库转换为.NET 8:https://github.com/LuBu0505/redis-copy-net8
|
20天前
|
存储 NoSQL 安全
Redis系列学习文章分享---第十五篇(Redis最佳实践--设计优雅的key+合适的数据结构+持久化如何配置+慢查询问题解决)
Redis系列学习文章分享---第十五篇(Redis最佳实践--设计优雅的key+合适的数据结构+持久化如何配置+慢查询问题解决)
31 1
|
12天前
|
存储 NoSQL Redis
|
13天前
|
Java Redis 数据安全/隐私保护
Redis13的Java客户端-Jedis快速入门,建立连接的写法,ip地址,设置密码密码,选择库的写法
Redis13的Java客户端-Jedis快速入门,建立连接的写法,ip地址,设置密码密码,选择库的写法
|
13天前
|
NoSQL Redis
Redis11-----Sortedset类型,SortedSet底层是由数据树实现的,SortedSet删除同学,获取Amy同学分数,获取Rose同学排名,查询80分以下的学生,给Amy同学加2分
Redis11-----Sortedset类型,SortedSet底层是由数据树实现的,SortedSet删除同学,获取Amy同学分数,获取Rose同学排名,查询80分以下的学生,给Amy同学加2分
|
13天前
|
NoSQL Java Redis
Redis09-----List类型,有序,元素可以重复,插入和删除快,查询速度一般,一般保存一些有顺序的数据,如朋友圈点赞列表,评论列表等,LPUSH user 1 2 3可以一个一个推
Redis09-----List类型,有序,元素可以重复,插入和删除快,查询速度一般,一般保存一些有顺序的数据,如朋友圈点赞列表,评论列表等,LPUSH user 1 2 3可以一个一个推
|
14天前
|
存储 缓存 NoSQL
网页设计,若依项目修改(It must be done)04在线用户展示---仅仅从Redis取一下数据做展示,查看若依存储的资料,用RDM
网页设计,若依项目修改(It must be done)04在线用户展示---仅仅从Redis取一下数据做展示,查看若依存储的资料,用RDM
|
20天前
|
存储 JSON NoSQL
深入解析RedisJSON:在Redis中直接处理JSON数据
深入解析RedisJSON:在Redis中直接处理JSON数据
|
21天前
|
存储 NoSQL 算法
Redis数据组织揭秘:全局哈希表
Redis数据组织揭秘:全局哈希表