一、基本概念

Redis是一个开源的存储键值对的非关系型数据库,是内存数据库,用作数据库、缓存、消息队列和分布式锁。Redis提供了数据结构,如string、hash、list、set、zset、bitmap、hyperloglog、GEO、stream。Redis具有不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster提供高可用性和自动分区。

1、非关系性数据库,存储的是键值对数据,而且是内存数据库,因此速度很快

关系型数据库&非关系型数据库:

关系型数据库是基于关系模型的数据库,数据之间纯在一对一、一对多、多对多等关系,可使用SQL语句进行查询

非关系型数据库存的是键值对或者文档。图关系等,具有良好的可扩展性和高可用性

2、有两种持久化方式:RDB和AOF

3、除了做数据库还可以做消息队列、分布式锁

 

二、数据结构

1、五种基本数据结构:string、list、set、hash、zset

 

2、四种特殊结构:bitmap、hyperloglog、GEO、stream

 

三、持久化

1、RDB:创建数据库在某个时间节点上的快照

有两个命令来生成快照文件:save和bsave

save会阻塞主线程,bsave会fork一个子线程来保存快照,不会阻塞主线程

2、AOF:先执行命令,再把命令写入AOF日志

AOF 持久化功能的实现可以简单分为 5 步:

  1. 命令追加(append):所有的写命令会追加到 AOF 缓冲区中。
  2. 文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。
  3. 文件同步(fsync):AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。
  4. 文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
  5. 重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。

有三种持久化方式:

1、always:每个写命令都会写入AOF文件

2、everysec:每秒同步一次

3、no:让操作系统决定何时同步

AOF文件变得太大时就会对AOF文件进行重写,会删除对某个键值对修改的多条命令,保留最新的状态

 

RDB和AOF对比:

1、RDB存储的是二进制文件,因此体积更小

2、使用 RDB 文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。

3、RDB 的数据安全性不如 AOF,没有办法实时或者秒级持久化数据。

4、AOF 文件便于分析并且可以直接操作来解决一些问题。

 

四、redis生产问题

1、缓存穿透

大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。

解决方法:布隆过滤器

是多个哈希函数和一个位数组组成的数据结构,可以快速判断海量数据中是否存在给定数据。

但是布隆过滤器存在误判:布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

原因:

  1. 判断一个元素是否存在会先使用的哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)。
  2. 根据得到的哈希值,在位数组中把对应下标的值置为 1。

但是可能存在哈希冲突,导致不同的字符串可能哈希出来的位置相同。

 2、缓存击穿

请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。

解决方法:

  • 设置热点数据永不过期或者过期时间比较长。
  • 针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
  • 请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力

3、缓存雪崩

缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。造成原因可能是redis服务宕机

解决方法:

针对 Redis 服务不可用的情况:

  1. 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
  2. 限流,避免同时处理大量的请求。

针对热点缓存失效的情况:

  1. 设置不同的失效时间比如随机设置缓存的失效时间。
  2. 缓存永不失效(不太推荐,实用性太差)。
  3. 设置二级缓存。