Redis 是什么
- Redis 是一个基于内存的NoSql类型的数据存储服务。
- Nosql即not only sql,非关系型数据库,区别于传统关系型数据库的固定格式的行+列,Nosql的数据存储没有固定的格式,并且可以进行横向扩展。例如redis,HBase,MongoDB,图数据库等。
- Redis的全称为Remote Dictionary Server,意为远程字典服务,是一个开源的基于C语言的K-V形式的数据库,并提供了多种语言的API。
与memcached区别
两者都是内存形式的数据存储中间件,早期项目用memcached的多一些,但是随着redis普及之后,得益于它丰富的数据类型迅速获得开发者青睐,并抢占了memcached的市场,redis也确实够稳定,在软件迭代更新频繁的互联网中持续十几年依旧火热不止,暂时还没有一款他的平替,性能强悍,社区活跃,并且很好地支持了分布式场景,是开发者手上的一大利器。
五大基本类型
上文说到Redis支持丰富的数据类型,具体的,它支持字符串、哈希表、列表、集合、有序集合这些基本类型以及bitmap,hyperloglog等进阶数据类型。
String
- String是Redis最基础的数据结构,也是最常用到的类型。其他四种类型也是基于字符串类型构建的。
- String类型的值最大能存储512MB,可以使简单字符串,复杂的xml/json字符串,音视频图像等二进制流。
应用场景
- 缓存 前后端项目中最常见的用法,存储token用户信息。还有其他字符类型的数据都可以设置缓存,避免直接访问数据库,提高了查询效率,但是要做好数据的一致性。
List
- 列表类型用于存储多个有序元素
- 一个列表中可以存储一至多个元素,最多支持存储2^32-1个元素
- 支持从列表两端进行插入和弹出元素,支持读取指定范围的元素集,可以充当队列或栈的角色
- 列表内的元素是有序的,可重复的,支持通过下标获取指定的元素
应用场景
- 消息队列 基于以上特性,可以用list实现阻塞队列,使用左进右出的命令完成设计,生产者通过lpush从左边插入消息,多个消费者使用brpop阻塞弹出链表尾部数据
- 文章列表 博客网站的文章列表,当文章很多时,需要分页展示,可以用list存储,不仅有序,而且支持按照固定范围获取数据,解决了分页查询的问题,提高了查询效率
Set
- 集合类型的存储,但是set是无序的,不可重复的
- 支持集合内的增删改查,并且支持多个集合间的交集、并集、差集操作
应用场景
- 标签 浏览博客网站的共同话题、共同爱好的永科可以用标签进行归类
- 统计 利用元素的不可重复做去重统计功能
sorted set
- 即zset,有序的不可重复的集合
应用场景
- 排行榜 有序不重复集合的经典实用场景,例如视频网站对用户上传的视屏做排行榜,榜单参考的维度可能是点赞、播放量、收藏等多个方面
hash
- key field value 结构的存储规则,适合存储关系型对象
应用场景
- 整个对象存储
进阶数据类型
geospatial
- 存储地理空间位置,即经纬度信息
应用场景
- 附近的人
- 位置共享
- 地图直线距离展示
Hyperloglog
- 基数统计,无论输入的内容多大,hyperloglog占用固定12kb空间,计算出2^64个不同元素的基数,非常节省空间,但是可能存在误差
应用场景
- 网页统计UV(浏览用户数量,同一天一个ip多次访问算一次,目的是计数,比set节省空间)
bitmap
- 想象成一长条数组,每个格子只能存0或1
- 数组最大长度可达2^32bit,即512MB
应用场景
- 统计时间周期内的活跃用户数
- 统计打卡数
Redis持久化
作为一种内存数据库,当服务器进程退出时,存在数据丢失的风险,因此有了两种持久化方案:RDB和AOF,将内存数据落到磁盘上,等服务重启即可加载。
RDB
- 保存特定时间点的数据快照
- 进行rdb时,redis主进程不会做io操作,会fork一个子进程将数据集写入临时rdb文件中,完成新rdb文件写入后,用新文件替换旧文件
- rdb只能保存某个时间间隔的数据,如果中途Redis服务意外停止了,会丢失一段时间内的数据
AOF
- 以日志的形式记录每个写操作,行业内通用是每秒执行一次
- 重写,随着Redis运行时间变长,AOF日志文件越来越大,此时就要用重写机制来合并相同操作指令
- 手动触发 bgrewriteaof
- 自动触发 根据配置规则(redis.config)no-appendfsync-on-rewrite : yes ,开启重写;auto-aof-rewrite-percentage 100 意为上次重写后文件大小增长100%再次触发重写;auto-aof-rewrite-min-size 64mb意为当文件至少达到64mb后触发重写
主从复制
- 将一台Redis服务器的数据复制到其他的Redis服务器
- 故障恢复 当主节点出现问题时,可以切换为由从节点提供服务
- 负载均衡 读写分离:由主节点提供写服务,从节点提供读服务,在写少读多的场景中,通过多个从节点分担读负载,提高Redis集群并发量
缓存问题
缓存穿透
- 攻击者用缓存中不存在的key发起大量查询,导致请求直接打到数据库
解决方案
- 接口层增加校验,用户鉴权,id基础校验
- 增加key-null的缓存值,有效时间设置短点,防止攻击者用同一个key反复请求
- 布隆过滤器 如果有-可能有,如果没有-肯定没有,快速判断key是否存在,不存在则直接返回
缓存击穿
- 某个热点缓存由于时间到期二失效,导致大量请求打到数据库
解决方案
- 设置热点数据永不过期策略
- 接口接入限流与熔断方案,一来防止攻击者恶意刷接口,二来是有熔断策略,当接口中某些服务不可用时快速返回默认,不影响整条调用链路
缓存雪崩
- 缓存中大量数据到达过期时间,大量请求直接打到数据库
解决方案
- 缓存数据的活期时间要分散、随机设置,防止同一时间大量失效
- 分布式部署,把热点数据均匀分布在不同的服务器上
- 大热数据设置永不过期
总结
本文罗列了当下流行的内存数据库Redis的常见面试题和知识点,方便各位读者做内容提炼和知识归纳总结。