Redis的常见的用法

为什么使用Redis

  1. 性能:在遇到数据库中经常被查询的字段可以将它存在Redis中提高效率

    • Redis为什么快

  2. 并发:防止并发状态下大量请求直达数据库,造成数据库连接异常

单线程的redis为什么这么快

  1. 纯内存操作

  2. 单线程避免了频繁的上下文切换

  3. 采用了非阻塞的I/O多路复用机

    • 操作系统使用一个线程去监听socket连接,当监听到读操作或写操作的时候,就把数据交给应用层;

Redis只有单线程吗

redis的单线程主要是指Redis的网络I/O线程;Redis的持久化、集群同步等操作,都是由另外的线程执行

  • 在redis的4.0版本之后:Redis添加了多线程的支持,主要体现在大数据的异步删除功能上;

  • 在Redis的6.0版本之后:新增了多线程I/O读写并发的能力

    采用了多个线程处理网络I/O请求,这是因为网络硬件的提升,redis的性能瓶颈有时会出现在网络I/O的处理上,所以为了提高网络请求的并行度,6.0对于多线程采用了并行处理,但是读写命令,Redis仍然是单线程处理

缓存击穿

Redis中一个热点key在失效的同时,大量的请求过来,从而会全部到达数据库,压垮数据库。

解决

  1. 热点数据永不过期:对于某些场景不适合

  2. 定时更新:

  3. 互斥锁:解决缓存击穿常用的方式,当Redis根据key获取的value为空时,添加互斥锁,并从数据库更新数据,若其他线程请求该key,则获取锁失败,睡眠一段时间后重试。

缓存穿透

缓存和数据库中都没有的数据,可用户还是源源不断的发起请求,导致每次请求都会到数据库,从而压垮数据库

解决

  1. 业务层校验:对于错误的请求直接返回

  2. 不存在的数据设置短过期时间

  3. 布隆过滤器

缓存雪崩

Redis中缓存的数据大面积同时失效,或者Redis宕机,从而会导致大量请求直接到数据库,压垮数据库。

解决

  1. 设置有效期均匀分布

  2. 数据预热:对于即将来临的大量请求,可以提前走一遍系统,提前缓存,设置不同的过期时间

  3. 保证Redis服务高可用:前面我们介绍过Redis的哨兵模式和集群模式,为防止Redis集群单节点故障,可以通过这两种模式实现高可用。  

为什么 Redis 将其整个数据集保存在内存中?

Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度会严重影响redis的性能。

redis客户端缓存

优点

  1. 数据以非常小的延迟提供

  2. 数据库系统接受的查询较少,从而允许他为较少节点数的相同数据集提供服务(即为热点数据提供服务)

redis过期策略及内存淘汰机制

  • redis采用的是定期删除+惰性删除策略。

  • 为什么不用定时删除策略?

    定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.

  • 定期删除+惰性删除是如何工作的呢?     定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。因此在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。

    • 惰性删除容易造成内存占用过多的情况

淘汰策略:

noeviction:内存不足以容纳新写入的数据,新写入会报错,不推荐;

allkeys-lru:内存不足以容纳新写入的数据,在键空间中,移除最近最少使用的key,推荐,都在用;

allkeys-random:内存不足以容纳新写入的数据,在键空间中,随机删除,不推荐;

volatile-lru:只从设置过期时间的key中删除最近最少使用;不推荐

volatile-random:只从设置过期时间的key中随机删除;不推荐

volatile-ttl:从设置过期时间的key中删除最早过期的;不推荐

Redis和数据库双写一致性问题

  • redis与数据库只能保证最终一致性,而不能保证强一致性;

  1. 先删除缓存,再更新数据库;

    • 假设A查询,B更新,可能会造成双写一致性问题

    B更新,删除缓存;

    A查询,缓存无数据;

    A从数据库中查到旧值,

    A将旧值更新到缓存;

    B更新数据库完毕

    可以使用延时双删解决这个问题

    (1)先淘汰缓存 (2)再写数据库(这两步和原来一样) (3)休眠一定时间,再次淘汰缓存

    如果使用了MySQL读写分离架构

    还是使用双删延时策略,只是,睡眠时间修改为在主从同步的延时时间基础上,加几百ms

    吞吐量降低怎么办

    将第二次删除操作设置为异步的

    如果第二次删除失败则么办?

  2. 先更新数据库,再删除缓存

    失效:先把数据放入数据库中,成功后,再让缓存失效

    A查询,B更新

    (1)缓存刚好失效 (2)请求A查询数据库,得一个旧值 (3)请求B将新值写入数据库 (4)请求B删除缓存 (5)请求A将查到的旧值写入缓存

    • 这种发生错误的概率很小

三种Redis持久策略

1. RDB(半持久化的方式)

  1. 概述

RDB的方式是将某一时刻的数据记录下来,而不是记录操作,因此在恢复的时候,只需要把RDB文件读入到内存,就可以完成快速恢复;

按照配置不定期地通过异步的方式、快照的形式直接把内存的数据持久化到磁盘的一个dump.rdb文件(二进制文件)中,

redis默认的持久化方式,它配置在它的配置文件(redis.conf)中。

  • RDB快照的时候会不会阻塞线程:

    save会,bgsave会创建一个子线程,所以不会;

  • 如果在bgsave快照的时候主线程执行操作,Redis怎么做

    如果是读操作,则没有影响;写操作:被修改的数据会复制一份副本,然后bgsave子线程会把副本数据写入RDB文件;

  1. 优缺点

  • 优点:只包含一个文件,讲一个单独的文件转移到其他存储媒介上,对于文件备份,灾难恢复而言,比较实用。

  • 缺点:系统一旦在持久化策略之前出现宕机现象,此前还没有持久化的数据将会丢失。

  1. 配置

  • 在配置文件6379.conf中 save 900 1 #表示在900秒之后,如果至少有一个key发生变化,则将数据集的快照dump到dump.rdb文件中。

2. AOF(全持久化的方式)

  1. 概述

在Redis执行命令,把数据写入到内存,将命令写入文件当中(将日志记录到文件);

Redis默认是不支持这种全持久化方式的,需要在配置文件中将appendonly no改为appendonly yes。

  • redis为什么会在命令执行成功后才写入文件,而不是之前

    因为Redis在写入日志之前,是不会对命令进行检查的,所以就可以只记录成功的命令;

    风险是可能会丢失数据,在命令成功之后宕机

  1. 优缺点

  • 优点:数据安全性高,对日志文件的写入是append模式,因此即使再写入中发生了宕机问题,也不会破坏日志中已存在的内容。

  • 缺点:对于数量相同的数据集来说,aof文件通常比rdb文件大,因此rdb文件回复的速度大于aof文件

  1. 配置

在 Redis 的配置文件中存在三种同步方式,它们分别是:

  • appendfsync always #每次有数据修改发生时都会都调用 fsync 刷新到 aof 文件,非常慢, 但是安全;

  • appendfsync everysec #每秒钟都调用 fsync 刷新到 aof 文件中,很快,但是可能丢失一秒内 的数据,推荐使用,兼顾了速度和安全;

  • appendfsync no #不会自动同步到磁盘上,需要依靠 OS(操作系统)进行刷新, 效率快,但是安全性就比较差;

3. AOF和RDB混合持久化

把数据以RDB的方式写入文件,之后的操作命令以AOF的格式存入文件,既保证了Redis的重启速度,又降低了数据丢失的风险

4. AOF和RDB持久方式的区别

AOF往往在运行效率上慢于RDB,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

如果缓存数据安全性要求比较高的话,使用AOF持久化方式(比如项目中的购物车)

如果对于大数据集要求效率高的话,可以使用默认的RDB持久化方式。

两种持久化方式可以同时使用。

Redis的高可用

redis高可用有三种方式

1. 主从复制(最基础)

基础保证,将原本的一台Redis服务器,同步数据到多台服务器上,实现主写从读的读写分离,可以承载更多的并发服务

2. 哨兵模式

因为主从同步模式服务器宕机后需要手动恢复,Redis添加了哨兵模式监控主从服务器,并提供自动容灾恢复的功能

3. Redis集群(最常用)

一种去中心化的运行模式,将数据分布在不同的服务器上,降低对于单主节点的压力和依赖,从而提高读写效率

一个切片集群有16384个哈希槽,每个键值都会根据key值映射到对应的哈希槽中

哈希槽的映射规则:

  1. 平均分配:

  2. 手动分配:

Redis分布式锁是怎么回事

先拿setnx来争抢锁,抢到之后在使用expire给锁加一个过期时间防止忘记释放;

  • 扩展:如果在setnx之后expire之前进程意外carsh或者是重启维护了,怎么办

    思考之后,记得redis好像有一个把setnx和expire合成一条指令来用的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值