基础
什么是Redis?
Redis 是一款非常流行的NoSQL数据库,一个高性能的 key-value 数据库。
整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据 flush 到硬盘上进行保存。
缺点:由于他受到物理内存的限制,因此无法用作海量数据的高性能读写。
为什么 Redis 需要把所有数据放到内存中?
- Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘,所以 Redis 具有高速读写和数据持久化的特征
- 如果程序直接与磁盘交互,磁盘 IO 速度会严重影响 Redis 的性能
- 内存的硬件成本降低,使得 Redis 更受欢迎。
应用
Redis 能用来做什么?
会话缓存,排行榜,计数器,发布,订阅,地图信息分析(附近的人)
- 记录帖子的点赞数、评论数和点击数 (
hash
)。 - 记录用户的帖子 ID 列表 (排序),便于快速显示用户的帖子列表 (
zset
)。 - 记录帖子的标题、摘要、作者和封面信息,用于列表页展示 (
hash
)。 - 记录帖子的点赞用户 ID 列表,评论 ID 列表,用于显示和去重计数 (
zset
)。 - 缓存近期热帖内容 (帖子内容空间占用比较大),减少数据库压力 (
hash
)。 - 记录帖子的相关文章 ID,根据内容推荐相关帖子 (
list
)。 - 如果帖子 ID 是整数自增的,可以使用 Redis 来分配帖子 ID(
计数器
)。 - 收藏集和帖子之间的关系 (
zset
)。 - 记录热榜帖子 ID 列表,总热榜和分类热榜 (
zset
)。 - 缓存用户行为历史,进行恶意行为过滤 (
zset
,hash
)。
Reids数据类型
-
常用5种数据类型:string,list,set,zset,hash
一个字符串类型的值能存储最大容量是多少?512M
-
三种特殊数据类型:
-
geospatial:地理位置
-
hyperloglog:基础统计,统计一个集合中不重复的数据,使用位运算的方式,但是存在0.81%错误率。
-
bitmap:位图,只记录0和1。
-
Redis是单进程单线程的吗?
Redis是单进程单线程的,Redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销。
多线程处理会涉及到锁,而且多线程处理会涉及到线程切换而消耗CPU。因为CPU不是Redis 的瓶颈,Redis的瓶颈最有可能是机器内存或者网络带宽。
单线程无法发挥多核CPU性能,不过可以通过在单机开多个Redis实例来解决。全新的redis6.0,正式支持多线程。
什么是缓存? 缓存雪崩、缓存穿透、缓存击穿的含义以及解决方案?
数据交换的缓冲区(称作Cache),当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找。
缓存雪崩
大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。
-
解决方案
可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。
缓存穿透
访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。
-
解决方案
采用布隆过滤器,使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤;
访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间。
缓存击穿
一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。
-
解决方案
在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。
Redis 数据淘汰策略有哪些?
Redis 提供 6种内存淘汰策略
- Volatile-lru:从设置了过期时间的数据集中,选择最近最少使用的数据释放。
- Allkeys-lru:从数据集中(包括设置过期时间以及未设置过期时间的数据集中),选择最近最少使用的数据释放。
- Volatile-random:从设置了过期时间的数据集中,随机选择一个数据进行释放。
- Allkeys-random:从数据集中(包括了设置过期时间以及未设置过期时间的数据集)随机选择一个数据进行入释放。
- Volatile-ttl:从设置了过期时间的数据集中,选择马上就要过期的数据进行释放。
- Noeviction:不删除任意数据(但Redis还会根据引用计数器进行释放),这时如果内存不够时,会直接返回错误。
Redis提供了哪几种持久化方式?
Redis主要提供了两种持久化机制:RDB
和AOF
:
-
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
-
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
怎么理解 Redis 事务?
redis对事务的支持目前还比较简单。redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。 由于redis是单线程来处理所有client的请求的所以做到这点是很容易的。
redis没有回滚的概念,已经执行的动作不能undo
。当事务在执行EXEC命令之前出现错误,则redis会清空事务队列,放弃执行事务。在EXEC之后redis批量执行命令时产生的错误会被忽略,其他命令继续执行(这是全部执行的真正含义)。在执行的过程中,redis命令只会因为错误的语法而失败,因此,事务无罪。
Redis如何做内存优化?
尽可能使用散列表
(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小, 所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用 户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的 所有信息存储到一张散列表里面。
什么是单点登录?
单点登录(Single Sign On),简称为SSO
,是比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
简单来说,单点登录就是在多个系统中,用户只需一次登录,各个系统即可感知该用户已经登录。
原理: SSO系统生成一个token
,并将用户信息存到Redis中,并设置过期时间。
其他系统请求SSO系统进行登录,得到SSO返回的token,写到Cookie中
每次请求时,Cookie都会带上,拦截器得到token,判断是否已经登录。
假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以 某个固定的已知的前缀开头的,如果将它们全部找出来?
使用 keys
指令可以扫出指定模式的 key 列表。
如果这个 redis 正在给线上的业务提供服务,那使用 keys 指令会 有什么问题?
redis 的单线程的,keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时 候可以使用 scan
指令,scan指令可以无阻塞的提取出指定模式的 key 列表,但 是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间 会比直接用 keys 指令长。