Redis面试题总结

目录

1 Redis的数据类型

1.1 string

1.2 hash

1.3 list

1.4 set

1.5 zset

1.6 bitmap

1.7 hyperloglog

1.8 geo

2 Redis的底层结构

3 数据淘汰策略

4 Redis持久化

5 Redis分布式锁的实现

6 缓存穿透和缓存雪崩

7 Redis哈希槽


Redis的数据类型

1.1 string

格式: set key value
string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
string类型是Redis最基本的数据类型,一个键最大能存储512MB。

1.2 hash

格式: hmset name  key1 value1 key2 value2
Redis hash 是一个键值(key=>value)对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

1.3 list

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
格式: lpush  name  value
在 key 对应 list 的头部添加字符串元素
格式: rpush  name  value
在 key 对应 list 的尾部添加字符串元素
格式: lrem name  index
key 对应 list 中删除 count 个和 value 相同的元素
格式: llen name  
返回 key 对应 list 的长度

1.4 set

格式: sadd  name  value
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

1.5 zset

格式: zadd  name score value
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。

1.6 bitmap

bitmap使用二进制的存储方式,使用1bit标示一个关键字的状态。可使用与、或、非、异或等操作,适合用于统计累计用户/日均活跃用户等功能。

1.7 hyperloglog

本质上是字符串,但使用极小空间完成独立数量统计。需要注意的是hyperloglog是有错误率的(错误率0.81%),也就是说统计出来的值不一定是完全正确的。而且不能统计单条数据,只能统计全部数据。

1.8 geo

用于计算地理位置信息相关的一些功能。


2 Redis的底层结构

  • 简单动态字符串
  • 链表
  • 字典
  • 跳跃表
  • 整数集合
  • 压缩列表
数据类型 底层结构
string 整数值
embstr编码的简单动态字符串
简单动态字符串
hash 压缩列表
字典
list 压缩列表
双端链表
set 整数集合
字典
zset 压缩列表
跳跃表和字典

3 数据淘汰策略

redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:

  • volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  • allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-enviction(驱逐):禁止驱逐数据_func()

注意这里的6种机制,volatile和allkeys规定了是对已设置过期时间的数据集淘汰数据还是从全部数据集淘汰数据,后面的lru、ttl以及random是三种不同的淘汰策略,再加上一种no-enviction永不回收的策略。

使用策略规则:

  1. 如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用allkeys-lru
  2. 如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用allkeys-random

三种数据淘汰策略:

ttl和random比较容易理解,实现也会比较简单。主要是lru最近最少使用淘汰策略,设计上会对key按失效时间排序,然后取最先失效的key进行淘汰。


Redis持久化

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。

Redis 提供了两种持久化方式:RDB(默认) 和AOF 

RDB:rdb是Redis DataBase缩写,功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数

AOF:aof是Append-only file缩写,每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用

比较:

  1. aof文件比rdb更新频率高,优先使用aof还原数据。
  2. aof比rdb更安全也更大
  3. rdb性能比aof好
  4. 如果两个都配了优先加载AOF

Redis分布式锁的实现

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

如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

set key value ex 1000 nx(单条命令保证原子性),或者使用spring-boot-starter-data-redis中的setIfAbsent方法


缓存穿透和缓存雪崩

缓存穿透:
一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免:
1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。
缓存雪崩:
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
如何避免:
1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。


7 Redis哈希槽

Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。

你可能感兴趣的:(Redis,面试题总结)