- 什么是redis,存储类型、性能、数据结构、单条数据最大长度等介绍
- key-value类型的数据库
- 性能非常出色,每秒能处理超10万次读写操作
- 支持多种数据结构
- 单条value最大限制是1GB
- 相比于memcached,可以设置过期时间
- 局限于较小的数据量
- redis支持的数据类型
- String:最基本的类型,二进制安全,限制512MB
- List:简单的字符串列表,有序
- Set:无需的字符串合集
- ZSet:在set的基础上,每个元素关联一个double类型的分数
- Hash:键值对集合,类似于Map
- GEO:地理位置,底层为zset
- HyperLogLog:不精准的去重计数
- BigMap:位图,通过二进制位来记录0和1,节省空间
- redis的优势/NoSQL的优势
- 易扩展
- 大数据量高性能
- 灵活的数据模型
- CAP3选2是什么
- Consistency(强一致性)
- Availability(高可用性)
- Partition tolerance(分区容错性)
当下不可能同时满足3中特性,只能较好地满足其中两个,即:
- CA:单点集群,可扩展性不强
- CP:性能不高
- AP:一致性要求低
- redis的应用场景有哪些?
- 热点数据缓存
- 排行榜
- redis队列实现削峰
- 计数器
- 分布式锁
- 通常哪种硬件资源是redis的性能瓶颈?
- 内存空间
- 网络带宽
- redis为什么是单线程的?
- redis基于内存操作,CPU不是瓶颈,且单线程实现容易
- 单线程的优势和劣势?
- 优势:
- 单线程环境不需要各种锁,能节省资源
- 不存在线程切换导致的CPU消耗
- 劣势
- 无法充分发挥多核CPU的性能,一般通过单机开启多个redis实例完善
- 有哪几种数据淘汰策略?
- noeviction(默认):内存达到限制后返回错误
- allkeys-lru:回收最少使用的键
- allkeys-random:随机回收
- volatile-lru:在过期的键中回收最少使用的键
- volatile-random:随机回收过期的键
- volatile-ttl:回收过期的键且优先回收存活时间较短的键
- redis为什么这么快?
- 完全基于内存,避免了磁盘IO
- 使用了高性能的数据结构,如跳表、hash
- 采用单线程,没有上下文切换,没有各种锁
- 使用基于IO多路复用机制的线程模型
- redis有几种持久化的方式、优缺点及应用场景是什么?
- 两种持久化方式
- RDB:备份是在指定的时间间隔内将内存中的数据集快照写入磁盘(单独fork一个子进程进行持久化,将数据写入一个临时文件中,再用这个临时文件替换上次持久化好的文件,整个过程中主进程不进行IO操作,保证高性能),恢复是将这个持久化文件(dump.rdb)放入redis-server的启动目录,启动时redis会自动将其中的数据导入。
- AOF:以日志的形式记录每个写操作,追加到指定的文件中,redis启动的时候会读取文件重新构建数据,即根据日志文件的内容将aof文件中的指令从头到尾再执行一次
- 优缺点
- RDB:简单快速,默认开启,适合大规模的数据恢复,每隔一定的时间做一次备份;如果redis意外关闭可能会丢失最后一次快照的所有修改,且再fork的时候内存中的数据被克隆了一份,需要考虑两倍的膨胀性以及服务可能会停顿一段时间。
- AOF:可设置触发机制,没修改一次或每秒中持久化一次,数据的完整性可得得到保障;但是aof文件要远大于rdb文件,恢复速度也比较慢
- 应用场景
- 只做缓存的时候,可以不开启持久化
- 如果同时开启两种持久化,那么优先载入AOF文件恢复数据(更完整)
- 默认开启了RDB,但是不建议只开启AOF,因为RDB更好备份,AOF不断变化不好备份,而且AOF可能有潜在的BUG
- 如果可以承受分钟以内的数据丢失,可以只使用RDB持久化,通常简历从机开启RDB
- 怎么保证缓存和数据库数据的一致性?
- 详见 https://juejin.cn/post/6850418121754050567
- redis事务是怎样的?
- 本质是一组命令的集合,一次性执行多个命令,再exec命令前被放入队列缓存中,并不会被执行
- 不保证原子性,没有回滚,遇到命令级错误则所有命令都不会执行,遇到语法性错误则后续命令继续执行
- 流程:multi开启事务,输入多条命令,exec执行或discard取消事务
- watch监控是悲观锁还是乐观锁
- 乐观锁
- 监控某条数据后,如果事务期间数据未被其他session改动,则事务执行成功,若被其他session改动,则事务执行失败
- 缓存穿透、缓存击穿、缓存雪崩
- 缓存穿透
- 重点在“透”,大量的请求查询不存在的key,即透过了缓存,直接请求数据库,叫缓存穿透。
- 解决:重点在于不信任用户的请求,有一个请求进来查key查不到对应的value,那么就将这个key保存到redis中,但是这种方案不实际(每次请求的key可能是不同的);缓存之前加一层布隆过滤器,在查询的时候先去布隆过滤器查询,不存在直接返回,不给透过缓存的机会。
- 缓存击穿
- 大量请求访问了一个key,但是这个key过期了,请求转而打到数据库,导致数据库压力过大,这种叫缓存击穿。
- 解决:重点在于key过期了,如果业务允许可以让key永远不过期;使用互斥锁,只有拿到锁才能够访问数据库,降低了同一时刻打在数据库的请求
- 缓存雪崩
- 大规模的缓存失效,导致大量的请求直接打到数据库上,数据库压力过大挂掉,这叫缓存雪崩。
- 解决:重点在于同一时间大规模的key失效,可以在设置失效时间的时候加上一个随机值;使用熔断机制;分库分表、读写分离或搭建redis集群,提高数据库的容灾能力