Redis相关概念以及缓存预热、缓存雪崩、缓存击穿、缓存穿透解决方案

单线程的Redis为什么这么块
  1. 纯内存操作
  2. 单线程操作,避免了频繁的上下文切换
  3. 采用了非阻塞I/O多路复用机制
Redis的数据类型,以及每种数据类型的使用场景
  1. String
  2. hash
  3. list
  4. set
  5. sorted set:比set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。
Redis持久化机制

Redis是一个支持持久化的内存数据库,通过持久化把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能到达恢复数据的目的。
实现:单独创建fork()一个子进程,把当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
RDB是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。
AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,当Redis重启会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
当两种方式同时开启时,数据恢复Redis会优选选择AOF恢复。

Redis删除策略
  1. 定时删除

    • 创建一个定时器,当key设置过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
    • 优点:节约内存,到时就删除,快速释放掉不必要的内存占用
    • 缺点:CPU压力很大,无论CPU此时负载多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
    • 总结:用处理器性能换取存储空间
  2. 惰性删除

    • 数据到达过期时间,不做处理,等下次访问该数据
      • 如果未过期,返回数据
      • 发现已过期,删除,返回不存在
    • 优点:节约CPU性能,发现必须删除的时候才删除
    • 缺点:内存压力大,出现长期占用内存的数据
    • 总结:用存储空间换取处理器性能
  3. 定期删除

    • 在这里插入图片描述
    • 周期性轮询redis库中时效性数据,采用随机抽取的策略,通过过期数据占比的方式删除
  4. 删除策略对比
    在这里插入图片描述

逐出算法
1. 新数据进入检测

当新数据进入redis时,如果内存不足怎么办?

  • Redis使用内存存储数据,在执行每一个命令前,会调用freeMemoryIfNeeded()检测内存是否充足。如果内存不满足新加入数据的最低存储要求,redis要临时删除一些数据为当前指令清理存储空间。清理数据的策略称为逐出算法。
  • 注意:逐出数据的过程不是100%能够清理出足够的可使用的内存空间,如果不成功则反复执行。当对所有数据尝试完毕后,如果不能达到内存清理的要求,将出现错误信息。
2. 影响数据逐出的相关配置
  • 最大可使用内存

maxmemory
占用物理内存的比例,默认为0,表示不限制。生产环境中根据需求设定,通常设置在50%以上。

  • 每次选取待删除数据的个数

maxmemory-samples
选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能。因此采用随机获取数据的方式作为待检测删除数据。

  • 删除策略

maxmemory-policy
达到最大内存后,对被挑选出来的数据进行删除的策略。

3. 删除策略
  1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  2. volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
  3. volatile-ttl :从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  4. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  5. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  6. allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
  7. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  8. no-enviction(驱逐):禁止驱逐数据,新写入操作会报错
Redis为什么是单线程的

因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。Redis利用队列技术将并发访问变成串行访问。

Redis事务

Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH四个原语实现的。
Redis会将一个事务中的所有命令序列化,然后按顺序执行。

  1. 如果在一个事务中的命令出现错误,那么所有的命令都不会执行。
  2. 如果在一个事务中出现运行错误,那么正确的命令会被执行。
  • MULTI命令用于开启一个事务,它总是返回OK。MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。
  • EXEC命令用于执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。当操作被打断时,返回空值nil。
  • 通过调用DISCARD,客户端可以清空事务队列,并放弃执行事务,并且客户端会从事务状态中退出。
  • WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。
缓存预热

缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统,这样可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题。用户直接查询事先被预热的缓存数据。

缓存雪崩

在一个较短的时间内,缓存中较多的key集中过期,所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
解决办法

  1. 构建多级缓存架构
  2. 数据有限策略调正,也就是把缓存失效时间分散开
缓存击穿

Redis中某个key过期,该key访问量巨大。多个数据请求读取Redis缓存均为命中,发起了大量对数据库同一个数据的访问,导致对数据库服务器造成压力。
解决办法

  1. 监测热点数据,设置热点数据永不过期。
  2. 加互斥锁
缓存穿透

缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空。
解决办法

  1. 缓存null:对查询结果为null的数据进行缓存
  2. 布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值