2020互联网公司面试 Redis必问技术点

Redis

介绍

key-value nosql非关系型数据库 单线程,c语言开发,效率高(完全基于内存,非阻塞IO,大部分命令时间复杂度都是O(1)所以速度快)。因为是单线程,时间复杂度为 O(N) 的 KEYS 命令,严格禁止在生产环境中使用!

Key

1. 不要使用过长的Key。例如使用一个1024字节的key就不是一个好主意,不仅会消耗更多的内存,还会导致查找的效率降低
2. Key短到缺失了可读性也是不好的,例如u1000flw比起user:1000:followers来说,节省了寥寥的存储空间,却引发了可读性和可维护性上的麻烦
3. 最好使用统一的规范来设计Key,比如object-type:id:attr,以这一规范设计出的Key可能是user:1000或comment:1234:reply-to
4. Redis允许的最大Key长度是512MB(对Value的长度限制也是512MB)

基本数据类型常用五种

1. String 是Redis的基础数据类型,Redis没有Int、Float、Boolean等数据类型的概念,所有的基本类型在Redis中都以String体现。
2. List 注意:链表结构,Redis的List实际是设计来用于实现队列,而不是用于实现类似ArrayList这样的列表的。如果你不是想要实现一个双端出入的队列,那么请尽量不要使用Redis的List数据结构。
3. Hash 理解成java的hashMap,存储对象比较实用,可以实现二元查找,如”查找ID为1000的用户的年龄”。比起将整个对象序列化后作为String存储的方法,Hash能够有效地减少网络传输的消耗
4. Set 是无序的,不可重复的String集合。
5. Sorted Set 是有序的、不可重复的String集合。Sorted Set中的每个元素都需要指派一个分数(score),Sorted Set会根据score对元素进行升序排序。如果多个member拥有相同的score,则以字典序进行升序排序。Sorted Set非常适合用于实现排名。

数据持久化

生产开启两种措施,RDB默认开启,AOP 配置文件:appendonly yes 开启

RDB(执行时间间隔生成rdb快照)

采用RDB持久方式,Redis会定期保存数据快照至一个rbd文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置Redis进行快照保存的时机:

save [seconds] [changes]

意为在[seconds]秒内如果发生了[changes]次数据修改,则进行一次RDB快照保存

优点:

1. 对性能影响最小。如前文所述,Redis在保存RDB快照时会fork出子进程进行,几乎不影响Redis处理客户端请求的效率。
2. 每次快照会生成一个完整的数据快照文件,所以可以辅以其他手段保存多个时间点的快照(例如把每天0点的快照备份至其他存储媒介中),作为非常可靠的灾难恢复手段。
3. 使用RDB文件进行数据恢复比使用AOF要快很多。

缺点:

1. 快照是定期生成的,所以在Redis crash时或多或少会丢失一部分数据。
2. 如果数据集非常大且CPU不够强(比如单核CPU),Redis在fork子进程时可能会消耗相对较长的时间(长至1秒),影响这期间的客户端请求。

AOF(把每一个写请求都记录在一个日志文件里)

AOF提供了三种fsync配置,always/everysec/no,通过配置项[appendfsync]指定:

1. appendfsync no:不进行fsync,将flush文件的时机交给OS决定,速度最快
2. appendfsync always:每写入一条日志就进行一次fsync操作,数据安全性最高,但速度最慢
3. appendfsync everysec:折中的做法,交由后台线程每秒fsync一次

优点:

1. 最安全,在启用appendfsync always时,任何已写入的数据都不会丢失,使用在启用appendfsync everysec也至多只会丢失1秒的数据。
2. AOF文件在发生断电等问题时也不会损坏,即使出现了某条日志只写入了一半的情况,也可以使用redis-check-aof工具轻松修复。
3. AOF文件易读,可修改,在进行了某些错误的数据清除操作后,只要AOF文件没有rewrite,就可以把AOF文件备份出来,把错误的命令删除,然后恢复数据。

缺点:

1. AOF文件通常比RDB文件更大
2. 性能消耗比RDB高
3. 数据恢复速度比RDB慢

架构演变集群高可用方案(延伸扩展问题等)

1. 普通主从模式:避免单点故障,读写分离,但是master挂了需要手动重启
2. 哨兵模式高可用:监控redis集群状态:主要功能两个(1)监控主数据库和从数据库是否正常运行。(2)主数据库出现故障时自动将从数据库转换为主数据库。
3. redis-cluster群集高可用:上面两个都是全量存储redis数据,浪费内存并且有木桶效应,此配置最低3主3从,设计成共有16384个hash slot(hash槽)。每个master分得一部分slot,其算法为:hash_slot = crc16(key) mod 16384 ,这就找到对应slot。

内存管理与数据淘汰机制

内存管理

在32位OS中,Redis最大使用3GB的内存,在64位OS中则没有限制。
在使用Redis时,应该对数据占用的最大空间有一个基本准确的预估,并为Redis设定最大使用的内存。否则在64位OS中Redis会无限制地占用内存(当物理内存被占满后会使用swap空间),容易引发各种各样的问题。
通过如下配置控制Redis使用的最大内存:

maxmemory 100mb

在内存占用达到了maxmemory后,再向Redis写入数据时,Redis会:

1. 根据配置的数据淘汰策略尝试淘汰数据,释放空间
2. 如果没有数据可以淘汰,或者没有配置数据淘汰策略,那么Redis会对所有写请求返回错误,但读请求仍然可以正常执行

在为Redis设置maxmemory时,需要注意:
如果采用了Redis的主从同步,主节点向从节点同步数据时,会占用掉一部分内存空间,如果maxmemory过于接近主机的可用内存,导致数据同步时内存不足。所以设置的maxmemory不要过于接近主机可用的内存,留出一部分预留用作主从同步。

数据淘汰机制

Redis提供了5种数据淘汰策略:

1. volatile-lru:使用LRU算法进行数据淘汰(淘汰上次使用时间最早的,且使用次数最少的key),只淘汰设定了有效期的key
2. volatile-random:随机淘汰数据,只淘汰设定了有效期的key
3. allkeys-lru:使用LRU算法进行数据淘汰,所有的key都可以被淘汰
4. allkeys-random:随机淘汰数据,所有的key都可以被淘汰
5. volatile-ttl:淘汰剩余有效期最短的key

最好为Redis指定一种有效的数据淘汰策略以配合maxmemory设置,避免在内存使用满后发生写入失败的情况。
一般来说,推荐使用的策略是volatile-lru,并辨识Redis中保存的数据的重要性。

缓存穿透,缓存雪崩,缓存击穿

缓存穿透

缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

1. 过滤,首先对key的定义进行约束规范,对不符合的key直接返回,或者采用算法or存储key的方案来校验key的准确性。
2. 如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但必须设置过期时间。防止后续真实创建这个key。

缓存雪崩

如果缓存key集中在一段时间内失效,并且查询压力大,所有的查询都落在数据库上,造成了缓存雪崩。

1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
3. 设置热点数据永远不过期。

缓存击穿

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

1. 设置热点数据永远不过期。
2. 加互斥锁
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章