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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 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为主


相关文章
|
2月前
|
存储 NoSQL Redis
阿里云高性能数据库Tair(兼容 Redis)收费价格,稳定可靠成本低
阿里云高性能云数据库Tair兼容Redis,提供Redis开源版和Tair企业版,支持多种存储介质与灵活扩展,适用于高并发场景。Tair具备亚毫秒级稳定延迟,保障业务连续性。价格方面,Redis开源版年费从72元起,Tair企业版年费从1224元起,具体费用根据配置不同有所变化。
|
6月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
7月前
|
存储 NoSQL 数据库
Redis 逻辑数据库与集群模式详解
Redis 是高性能内存键值数据库,广泛用于缓存与实时数据处理。本文深入解析 Redis 逻辑数据库与集群模式:逻辑数据库提供16个独立存储空间,适合小规模隔离;集群模式通过分布式架构支持高并发和大数据量,但仅支持 database 0。文章对比两者特性,讲解配置与实践注意事项,并探讨持久化及性能优化策略,助你根据需求选择最佳方案。
273 5
|
6月前
|
数据采集 存储 NoSQL
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
363 67
|
5月前
|
存储 缓存 NoSQL
告别数据僵尸!Redis实现自动清理过期键值对
在数据激增的时代,Redis如同内存管理的智能管家,支持键值对的自动过期功能,实现“数据保鲜”。通过`EXPIRE`设定生命倒计时、`TTL`查询剩余时间,结合惰性删除与定期清理策略,Redis高效维护内存秩序。本文以Python实战演示其过期机制,并提供最佳实践指南,助你掌握数据生命周期管理的艺术,让数据优雅退场。
371 0
|
5月前
|
NoSQL 测试技术 Redis
Redis批量删除Key的三种方式
Redis批量删除Key是优化数据库性能的重要操作,本文介绍三种高效方法:1) 使用通配符匹配(KEYS/SCAN+DEL),适合不同数据规模;2) Lua脚本实现原子化删除,适用于需要事务保障的场景;3) 管道批量处理提升效率。根据实际需求选择合适方案,注意操作不可逆,建议先备份数据,避免内存溢出或阻塞。
|
8月前
|
存储 NoSQL 算法
Redis分片集群中数据是怎么存储和读取的 ?
Redis集群采用的算法是哈希槽分区算法。Redis集群中有16384个哈希槽(槽的范围是 0 -16383,哈希槽),将不同的哈希槽分布在不同的Redis节点上面进行管理,也就是说每个Redis节点只负责一部分的哈希槽。在对数据进行操作的时候,集群会对使用CRC16算法对key进行计算并对16384取模(slot = CRC16(key)%16383),得到的结果就是 Key-Value 所放入的槽,通过这个值,去找到对应的槽所对应的Redis节点,然后直接到这个对应的节点上进行存取操作
|
8月前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致 2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中 这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中 1. 使用MQ异步同步, 保证数据的最终一致性 我们项目中会根据业务情况 , 使用不同的方案来解决Redis和Mysql的一致性问题 : 1. 对于一些一致性要求不高的场景 , 不做处理例如 : 用户行为数据 ,
|
8月前
|
NoSQL Redis
Redis的数据淘汰策略有哪些 ?
Redis 提供 8 种数据淘汰策略: 淘汰易失数据(具有过期时间的数据) 1. volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 2. volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰 3. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 4. volatile-random:从已设置过期
|
NoSQL 数据库 Redis
Redis设置使用几号库
Redis中SpringBoot项目中的配置: 1、引入 spring-boot-starter-redis(POM.XML) org.springframework.boot spring-boot-starter-redis   2、添加配置文件(application.
1477 0

热门文章

最新文章