理论
一、Redis数据结构相关
1.Redis 支持的数据类型
String字符串
**格式:**set key value string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。 string类型是Redis最基本的数据类型,一个键最大能存储512MB。
Hash(哈希)
格式: hmset name key1 value1 key2 value2 Redis hash 是一个键值(key=>value)对集合。 Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
List(列表)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边) **格式:**lpush name value 在 key 对应 list 的头部添加字符串元素 **格式:**rpush name value 在 key 对应 list 的尾部添加字符串元素 **格式:**lrem name index key 对应 list 中删除 count 个和 value 相同的元素 **格式:**llen name 返回 key 对应 list 的长度
Set(集合)
**格式:**sadd name value Redis的Set是string类型的无序集合。 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
zset(sorted set:有序集合)
**格式:**zadd name score value Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。 zset的成员是唯一的,但分数(score)却可以重复。
2.Redis有哪些常用的命令?
3.Redis有哪些应用场景
二、Redis事务
1.什么是事务
Redis 中的事务是一组命令的集合,是 Redis 的最小执行单位,一个事务要么都执行,要么都不执行。带有以下三个重要的保证:
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
- 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
Redis 事务的原理是先将属于一个事务的命令发送给 Redis,然后依次执行这些命令。
2.为什么redis事务不具备原子性
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
3. Redis 事务相关命令有哪些?
**DISCARD:**取消事务,放弃执行事务块内的所有命令。 **EXEC:**执行所有事务块内的命令。 **MULTI:**标记一个事务块的开始。 **WATCH:**Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断 **UNWATCH :**取消 WATCH 命令对所有 key 的监视。
三、Redis持久化和缓存管理
1.Redis持久化是什么?
用一句话可以将持久化概括为:将数据(如内存中的对象)保存到可永久保存的存储设备中。 持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、 XML 数据文件中等等。 也可以从如下两个层面来理解持久化: **应用层:**如果关闭( Close )你的应用,然后重新启动则先前的数据依然存在。 **系统层:**如果关闭( Shut Down )你的系统(电脑),然后重新启动则先前的数据依然存在。
2.Redis 持久化机制有哪些?
Redis 提供两种方式进行持久化。 **RDB 持久化:**原理是将 Reids 在内存中的数据库记录定时 dump 到磁盘上的 RDB 持久化。 **AOF(append only file)持久化:**原理是将 Redis 的操作日志以追加的方式写入文件。
3.Redis 持久化机制 AOF 和 RDB 有什么区别?
aof,rdb是两种 redis持久化的机制。用于crash后,redis的恢复。 rdb的特性如下:
- fork一个进程,遍历hash table,利用copy on write,把整个db dump保存下来。
- save, shutdown, slave 命令会触发这个操作。
- 粒度比较大,如果save, shutdown, slave 之前crash了,则中间的操作没办法恢复。
aof有如下特性:
- 把写操作指令,持续的写到一个类似日志文件里。(类似于从postgresql等数据库导出sql一样,只记录写操作)
- 粒度较小,crash之后,只有crash之前没有来得及做日志的操作没办法恢复。
**两种区别就是,**一个是持续的用日志记录写操作,crash后利用日志恢复;一个是平时写操作的时候不触发写,只有手动提交save命令,或者是关闭命令时,才触发备份操作。 选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。
4.RDB和AOF 持久化机制的优缺点
RDB优点
- RDB 是紧凑的二进制文件,比较适合备份,全量复制等场景
- RDB 恢复数据远快于 AOF
RDB缺点
- RDB 无法实现实时或者秒级持久化;
- 新老版本无法兼容 RDB 格式。
AOF优点
- 可以更好地保护数据不丢失;
- appen-only 模式写入性能比较高;
- 适合做灾难性的误删除紧急恢复。
AOF缺点:
- 对于同一份文件,AOF 文件要比 RDB 快照大;
- AOF 开启后,会对写的 QPS 有所影响,相对于 RDB 来说 写 QPS 要下降;
- 数据库恢复比较慢, 不合适做冷备。
5.Redis 淘汰策略有哪些?
Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。
Redis 的缓存淘汰策略有:
**noeviction:**当内存不足以容纳新写入数据时,新写入操作会报错。 **allkeys-lru:**当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。 **allkeys-random:**当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。 **volatile-lru:**当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。 **volatile-random:**当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
6.Redis 缓存失效策略有哪些?
定时过期策略
每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
惰性过期策略
只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
定期过期策略
每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
Redis中同时使用了惰性过期和定期过期两种过期策略。
所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。
**假设 redis 里放了 10w 个 key,都设置了过期时间,**你每隔几百毫秒,就检查 10w 个 key,那 redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。**注意,**这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的灾难。实际上 redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。
**但是问题是,定期删除可能会导致 很多过期 key 到了时间并没有被删除掉,那咋整呢?**所以就是惰性删除了。这就是说,在你获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。
**获取 key 的时候,如果此时 key 已经过期,就删除,不会返回任何东西。**但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?答案是:走内存淘汰机制。

