Redis入门

综述:根据官方文档可知,Redis是一个开源(BSD许可),内存数据结构存储,用作数据库,缓存和消息代理。它支持数据结构,如 字符串,散列,列表,集合,带有范围查询的排序集,位图,超级日志,具有半径查询和流的地理空间索引。Redis具有内置复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区。Redis一共支持五种数据类:string(字符串),hash(哈希),list(列表),set(集合)和zset(sorted set有序集合)。

一、Javaweb中为何要使用Redis?

对于一般的项目,使用数据库进行存储以此来完成读写就已经足够了,但是当项目访问的用户量很大时比如秒杀系统、抢购时,成千上万的请求需要在极短的时间内完成读写操作就显得力不从心,甚至会使服务器宕机。

但是就Redis而言,它的性能相对来说就比较优越了,Redis能读的速度是110000次/s,写的速度是81000次/s ,其性能远超数据库,而且还支持集群、分布式、主从同步等,并且它还支持一定的事务能力,这保证了高并发的场景下数据的安全和一致性。

Redis 在 Java Web 主要有两个应用场景:

①、存储 缓存 用的数据;
②、需要高速读/写的场合使用它快速读/写;

对数据库的操作中读的次数一般来说是要高于写的次数的,因此我们可以把常用的数据存进Redis中,这里Redis用作缓存,因为Redis是基于内存的,我们访问内存当然很快了,具体的流程大致如下:
在这里插入图片描述
由上图可知,当第一次请求的时候会读取数据库,然后把读取到的内容写入Redis,之后再次读取的时候就会从Redis直接读取,提高速度。但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完 Redis 的读/写之后,会去判断该高速读/写的业务是否结束,这个判断通常会在秒杀商品为0,红包金额为0时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将 Redis 的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。

上面的流程分析的是读操作,当写操作时到底用不用Redis呢?我们来分析可知,如果使用Redis更新或者写数据进数据库之后还要更新Redis,很是麻烦,所以当写操作的时候一般不用Redis。

推荐阅读:Redis【入门】就这一篇!

二、Redis过期机制

1、键的过期时间

我们很多情况下都会用到Redis,但是对于一些数据在使用了一次之后很长时间都没有再次使用,仅仅是临时存储,那么时间长了自然会导致数据累积,下面就来看Redis如何防止数据累加后大量占用存储空间的问题。

Redis是基于内存的,内存是十分昂贵的,我们大多数情况下会清除不常用的数据保存常用的数据,所以,对于Redis来说我们可以设置键的过期时间来解决。

设置键的生存时间可以通过EXPIRE或者PEXPIRE命令。
设置键的过期时间可以通过EXPIREAT或者PEXPIREAT命令。

PERSIST(移除过期时间)
TTL(Time To Live)返回剩余生存时间,以秒为单位
PTTL以毫秒为单位返回键的剩余生存时间

简单示例:
在这里插入图片描述
2、下Redis的过期策略

Redis的键的过期删除策略有三种:

①、定时删除(对内存友好,对CPU不友好)
到时间点上就把所有过期的键删除,但是若过期key很多,删除这些key会占用很多的CPU时间,在CPU时间紧张的情况下,CPU不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些key

②、惰性删除(对CPU极度友好,对内存极度不友好)
每次从键空间取键的时候,判断一下该键是否过期了,如果过期了就删除。但是若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)

③、定期删除(折中)
每隔一段时间去删除过期键,限制删除的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间做一次删除)。

Redis采用的是惰性删除+定期删除两种策略,所以说,在Redis里边如果过期键到了过期的时间了,未必被立马删除的!

3、Redis的内存淘汰机制

如果定期删除漏掉了很多过期key,也没及时去查(没走惰性删除),大量过期key堆积在内存里,导致redis内存块耗尽了,我们可以设置内存最大使用量,当内存使用量超出时,会施行数据淘汰策略。

Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略:

①、noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。

②、allkeys-lru:在主键空间中,优先移除最近未使用的key。

③、volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。

④、allkeys-random:在主键空间中,随机移除某个key。

⑤、volatile-random:在设置了过期时间的键空间中,随机移除某个key。

⑥、volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。

下面看看几种策略的适用场景:

allkeys-lru:如果我们的应用对缓存的访问符合幂律分布(也就是存在相对热点数据),或者我们不太清楚我们应用的缓存访问分布状况,我们可以选择allkeys-lru策略。

allkeys-random:如果我们的应用对于缓存key的访问概率相等,则可以使用这个策略。

volatile-ttl:这种策略使得我们可以向Redis提示哪些key更适合被eviction。

另外,volatile-lru策略和volatile-random策略适合我们将一个Redis实例既应用于缓存和又应用于持久化存储的时候,然而我们也可以通过使用两个Redis实例来达到相同的效果,值得一提的是将key设置过期时间实际上会消耗更多的内存,因此我们建议使用allkeys-lru策略从而更有效率的使用内存。

推荐阅读:
Redis学习笔记–Redis数据过期策略详解
Redis 内存淘汰机制

三、Redis持久化
Redis是基于内存的,如果我们不想办法把Redis持久化到硬盘上,当Redis出现故障重启后Redis中的数据将不复存在。Redis有两种不同的持久化方法:
①、RBD:

Redis会定期保存数据快照至一个rbd文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置Redis进行快照保存的时机。

RDB持久化可以手动执行,也可以根据服务器配置定期执行。RDB持久化所生成的RDB文件是一个经过压缩的二进制文件,Redis可以通过这个文件还原数据库的数据。
如save [seconds] [changes],意为在[seconds]秒内如果发生了[changes]次数据修改,则进行一次RDB快照保存,例如 save 60 100,会让Redis每60秒检查一次数据变更情况,如果发生了100次或以上的数据变更,则进行RDB快照保存。可以配置多条save指令,让Redis执行多级的快照保存策略。Redis默认开启RDB快照。

有两个命令可以生成RDB文件:

SAVE:会阻塞Redis服务器进程,服务器不能接收任何请求,直到RDB文件创建完毕为止。
BGSAVE:创建出一个子进程,由子进程来负责创建RDB文件,服务器进程可以继续接收请求。
Redis服务器在启动的时候,如果发现有RDB文件,就会自动载入RDB文件(不需要人工干预)

服务器在载入RDB文件期间,会处于阻塞状态,直到载入工作完成。
除了手动调用SAVE或者BGSAVE命令生成RDB文件之外,我们可以使用配置的方式来定期执行:

在默认的配置下,如果以下的条件被触发,就会执行BGSAVE命令
在这里插入图片描述
RDB的优点:

对性能影响最小。如前文所述,Redis在保存RDB快照时会fork出子进程进行,几乎不影响Redis处理客户端请求的效率。
每次快照会生成一个完整的数据快照文件,所以可以辅以其他手段保存多个时间点的快照(例如把每天0点的快照备份至其他存储媒介中),作为非常可靠的灾难恢复手段。
使用RDB文件进行数据恢复比使用AOF要快很多。

RDB的缺点:

快照是定期生成的,所以在Redis crash时或多或少会丢失一部分数据。
如果数据集非常大且CPU不够强(比如单核CPU),Redis在fork子进程时可能会消耗相对较长的时间,影响Redis对外提供服务的能力。
②、AOF

AOF是通过保存Redis服务器所执行的写命令来记录数据库的数据的。采用AOF持久方式时,Redis会把每一个写请求都记录在一个日志文件里。在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新。AOF默认是关闭的,如果要开启在配置文件(redis.windows.conf)中设置:appendonly改为yes,默认的是no,如下图
在这里插入图片描述
AOF持久化功能的实现可以分为3个步骤:

1、命令追加:命令写入aof_buf缓冲区
2、文件写入:调用flushAppendOnlyFile函数,考虑是否要将aof_buf缓冲区写入AOF文件中
3、文件同步:考虑是否将内存缓冲区的数据真正写入到硬盘

flushAppendOnlyFile函数的行为由服务器配置的appendfsyn选项来决定的:
在这里插入图片描述

appendfsync always     # 每次有数据修改发生时都会写入AOF文件。
appendfsync everysec   # 每秒钟同步一次,该策略为AOF的默认策略。
appendfsync no         # 从不同步。高效但是数据不会被持久化。

但是随着AOF不断地记录写操作日志,因为所有的操作都会记录,所以必定会出现一些无用的日志。大量无用的日志会让AOF文件过大,也会让数据恢复的时间过长。不过Redis提供了AOF rewrite功能,可以重写AOF文件,只保留能够把数据恢复到最新状态的最小写操作集。AOF rewrite可以通过BGREWRITEAOF命令触发。

注意:AOF重写不需要对现有的AOF文件进行任何的读取、分析。AOF重写是通过读取服务器当前数据库的数据来实现的。

Redis将AOF重写程序放到子进程里执行(BGREWRITEAOF命令),像BGSAVE命令一样fork出一个子进程来完成重写AOF的操作,从而不会影响到主进程。但是,主进程可能接收到新的写命令,新的写命令请求可能会导致当前数据库和重写后的AOF文件的数据不一致!为了解决数据不一致的问题,Redis服务器设置了一个AOF重写缓冲区,这个缓存区会在服务器创建出子进程之后使用,具体过程如下:
在这里插入图片描述

AOF的优点:

最安全,在启用appendfsync always时,任何已写入的数据都不会丢失,使用在启用appendfsync everysec也至多只会丢失1秒的数据。
AOF文件在发生断电等问题时也不会损坏,即使出现了某条日志只写入了一半的情况,也可以使用redis-check-aof工具轻松修复。
AOF文件易读,可修改,在进行了某些错误的数据清除操作后,只要AOF文件没有rewrite,就可以把AOF文件备份出来,把错误的命令删除,然后恢复数据。

AOF的缺点:

AOF文件通常比RDB文件更大
性能消耗比RDB高
数据恢复速度比RDB慢

③、RDB和AOF对过期键的策略

1、RBD
从内存数据库持久化数据到RDB文件,持久化key之前,会检查是否过期,过期的key不进入RDB文件。

从RDB文件恢复数据到内存数据库,数据载入数据库之前,同样会对key先进行过期检查,如果过期,不导入数据库
2、AOF
过期key对AOF没有任何影响

2.1、从内存数据库持久化数据到AOF文件:
当key过期后,还没有被删除,此时进行执行持久化操作(该key是不会进入AOF文件的,因为没有发生修改命令)
当key过期后,在发生删除操作时,程序会向AOF文件追加一条del命令(在将来的以AOF文件恢复数据的时候该过期的键就会被删掉)
2.2、AOF重写
重写时,会先判断key是否过期,已过期的key不会重写到AOF文件

参考文章:

聊聊redis数据持久化

从零单排学Redis【白银】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值