5.2.1 Redis 是什么?常⻅的应用场景?
redis是一个缓存数据库,是一个非关系型数据库的键值存储数据库
应用场景:内容缓存,主要用于处理大量数据的高访问负载;日志系统
5.2.2 Redis 常⻅数据类型有哪些?各自有什么应用场景?
String:存储的数据是普通的键值对可用String来进行存储
Hash:存储的数据是一组关联性较强的数据,如一个人的生日、年龄、姓名等一系列信息
List:存储的数据是列表、消息队列等
Set:存储的数据类型是不重复的列表可用
Sorted Set:存储的数据类型是有序的不重复的列表
5.2.3 非关系型数据库 Redis 和 MongoDB 数据库的结构有什么区别?
内存管理机制上,redis把所有的数据都放入到内存中,定期写入磁盘。当内存不足时,调用LRU算法删除数据;mongodb和mysql类似,只将索引文件放入内存中。当内存不足时,只将热点数据放入内存,其它的数据写入磁盘。
数据结构上,redis支持丰富的数据结构,如String、Hash、List等;mongoDB支持的数据结构单一,但支持丰富的数据表达、 索引
性能上,redis适合较小的数据运算;mongodb在海量的数据下性能更优
5.2.4 Redis 和 MongoDB 数据库的键(key)和值(value)的区别?
5.2.5 Redis 持久化机制是什么?有哪几种方式?
周期性的将内存中的数据写入到文件中,当redis宕机,重启后,可以从持久化文件中读取数据,恢复宕机前的状态
有RDB和AOF两种方式,RDB是周期性的持久化数据,AOF是把每条写入命令当作日志,写入到一个日志文件中,当redis宕机,重启后,从AOF文件中读取写入命令重新构建整个数据集。
5.2.6 Redis 的事务是什么?
可以一次性执行多个命令,本质上就是一组命令的集合
5.2.7 为什么要使用 Redis 作为缓存?
redis相对于其它的键值数据存储,能够存储丰富的数据类型、执行速度快、操作是原子性的,可以把数据复制到任意数量的从机
5.2.8 Redis 和 Memcached 的区别?
redis支持持久化,mencached不支持
redis支持丰富的数据类型,mencached只支持一种string
5.2.9 Redis 如何设置过期时间和删除过期数据?
设置过期时间的方法有四种:
1. EXPIRE <KEY> <time>:设置键的生存时间为time秒
2. PEXPIRE <KEY> <time>:设置键的生存时间为time毫秒
3. EXPIREAT <KEY> <time>:将键的过期时间设置为time所指定的秒数时间戳
4. PEXPIREAT <KEY> <time>:将键的过期时间设置为time所指定的毫秒数时间戳
删除数据一共有三种策略:
1. 立即删除:设置过期时间时,指定一个回调函数,当到达过期时间,由时间处理器自动执行键的删除操作
2. 惰性删除:过期了就过期了,不管。每次从dict中按照key取值时,先检查key是否过期,如果过期,删除key,并返回nil,没有过期返回键值
3. 定时删除:每隔一段时间,检查expires字典,删除过期的键。
5.2.10 Redis 有哪几种数据淘汰策略?
volatile-lru:从设置了过期时间的数据集中,选择最近最久没使用的数据释放
volatile-random:从设置了过期时间的数据集中,随机选择一个数据进行释放
volatile-ttl:从设置了过期时间的数据集中,选择马上就要过期的数据进行释放
allkeys-lru:从数据集中(过期时间有没有设置都算),选择最近最久没使用的数据释放
allkeys-random:从数据集中(过期时间有没有设置都算),随机选择一个数据进行释放
Noeviction:不删除任何数据,如果内存不足,直接返回错误
5.2.11 Redis 为什么是单线程的?
redis是用一个cpu对一块内存区域进行数据的读写操作,如果用多线程,会存在上下文切换,上下文切换会浪费时间和资源。所以对于redis这样的内存系统来说,没有上下文的切换效率是最高的。
一次cpu上下文切换的时间大概是1500ns,从内存中读取1MB连续数据的时间大概是250us,假如1mb的数据都是由多线程读取了1000次,那么就有1000次上下文切换的时间1500ns*1000=1500us。我单线程读取的时间只有250us,多线程光上下文切换的时间就有1500us了
同时,使用单线程也避免了数据安全性的问题,多线程操作为了处理数据安全问题,需要加锁,一旦加锁就会影响程序的执行效率
5.2.12 单线程的 Redis 为什么这么快?
单线程,没有上下文切换的开销、没有加锁解锁的开销
纯内存操作系统,数据全部存储在内存中
高效的数据结构
合理的数据编码
5.2.13 缓存雪崩和缓存穿透是什么?如何预防解决?
缓存穿透:指查询一个一定不存在的数据,缓存中不命中时会去查询数据库,如果查询不到则不写入缓存,以后这个不存在数据的请求都会去查询数据库,造成数据穿透
预防办法:
1. 布隆过滤
2. 缓存空对象,null变为一个值,设置过期时间5min-10min
缓存雪崩:指缓存系统重启或缓存集中失效,导致造成大量的缓存穿透,所有的查询都落到数据库,造成缓存雪崩
预防办法:
1. 缓存集中失效后,通过加锁或队列控制数据库写缓存的线程数量,如对一个key的操作只允许一个线程,其它线程等待
2. 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效,可以查询A2,A1过期时间设置短期,A2过期时间设置长期
3. 不同key,设置不同的过期时间,保证缓存不会同一时间失效
5.2.14 布隆过滤器是什么?
5.2.15 简单描述一下什么是缓存预热、缓存更新和缓存降级?
缓存预热:指系统上线后,将数据加载到缓存中,手动或定时刷新
缓存更新:指自动或触发清理过期或不需要的数据
缓存降级:指为保证核心业务可以使用,将部分关键数据降级处理,同时也可以避免缓存雪崩
5.2.16 如何解决 Redis 的并发竞争 Key 的问题?
1. 分布式锁+时间戳
i. 对key操作不要求顺序
准备一个分布式锁,大家去抢锁,抢到的先做set操作
ii. 对key操作要求顺序
预期按照顺序给key赋值,比如先操作系统a,再b,再c,此时如果b先控制锁赋值了,之后a抢到锁,会先查看自己的时间戳是否早于缓存中的,如果是,则不做set操作
2. 消息队列
5.2.17 写一个 Python 连接操作 Redis 数据库实例?
import redis
r=redis.Redis(host='localhost',port='6379')
r.set('foo','haha')
print(r.get('foo'))
5.2.18 什么是分布式锁?
在分布式系统中,防止多个进程之间相互干扰,避免同一时间对共享数据进行修改操作。
5.2.19 Python 如何实现一个 Redis 分布式锁?
5.2.20 如何保证缓存与数据库双写时的数据一致性?
先修改缓存为指定值,再去更新数据库,再去更新缓存。如果读请求过来了,先读缓存,如果缓存是指定值,进入循环,等待写请求完成,更新缓存。如果循环超时,则去读数据库,更新缓存。
5.2.21 集群是什么?Redis 有哪些集群方案?
5.2.22 Redis 常⻅性能问题和解决方案?
5.2.23 了解 Redis 的同步机制么?
5.2.24 如果有大量的 key 需要设置同一时间过期,一般需要注意什么?
5.2.25 如何使用 Redis 实现异步队列?
5.2.26 列举一些常用的数据库可视化工具?