Redis面试题相关知识整理
- 1.Redis的应用场景
- 2.Redis的特点
- 3.Redis对各种数据类型的操作
- 4.Redis的持久化机制
- 5.Redis的缓存穿透/缓存击穿/缓存雪崩问题
- 6.Redis的主从复制架构, sentinel哨兵模式
- 7.memcache与redis的区别
- 8.单线程的redis为什么这么快
- 9.Redis的过期策略以及内存淘汰机制
- 10.Redis为什么是单线程的
- 11.有没有尝试进行多机redis的部署? 如何保证数据一致的?
- 12.对于大量的请求怎么处理
- 13.Redis常见性能问题和解决方案
- 14.Redis实现分布式锁
- 15.Redis里面有1亿个key, 其中有10w个key是以某个固定的已知的前缀开头的, 如何将他们全部找出来
nosql数据库的特点: 一切皆字节
1.Redis的应用场景
1.排行榜应用, 取topN操作(sorted set)
2.计数器应用(string)
redis的命令都是原子性的, 你可以轻松地利用INCR, DECR命令来构建计数器系统
3.去重操作(set), 获取某段时间所有数据结果(排重)
4.构建队列系统
使用list可以构建队列系统, 使用sorted set甚至可以构建有优先级的队列系统
5.缓存操作
将数据直接存放到内存中, 性能优于Memcached, 数据结构更多样化
6.实时系统
7.保存对象(hash)
2.Redis的特点
高效率: redis的读取的速度大约11w次/s, 写的速度大于8.1w次/s
原子性: redis的所有操作都是原子性的.
稳定性: 持久化, 主从复制(集群)
支持多种数据结构: String, hash, list, set, sorted set
其他特性: 支持过期时间, 支持单行事务, 消息订阅
3.Redis对各种数据类型的操作
String:
set key value get key getset key value
incr key decr key
setex key seconds value setnx key value
strlen key
hash:
hset key field value hget key field
hkeys key hvals key
hexist key field
list:
lpushx key value rpushx key value llen key
lpop key rpop key
rpoplpush source destination
set:
sadd key member1 member2 spop key
ismember key member
sorted set:
zadd key score member zrem key member
key:
flushdb 清空redis数据
keys pattern 模糊匹配
expire key seconds ttl key del key
4.Redis的持久化机制
RDB: (默认开启)
redis提供的一种基于快照机制实现的持久化方案. 而快照就类似于照相机, 会将一个服务器某个时刻的一个状态整体保存下来, 快照文件一般都非常的小
save 900 1
save 300 10
save 60 10000
AOF:
redis提供的一种基于日志机制实现的持久化方案, 会将用户操作的所有命令整体的记录下来保存到日志文件中
appendonly yes
appendfsync always/everysec/no
5.Redis的缓存穿透/缓存击穿/缓存雪崩问题
redis的缓存穿透问题:
缓存穿透是指查询一条数据库中没有且缓存中没有的一条数据, 查了一遍缓存一遍数据库(这两次查询都是多余的), 缓存穿透的解决方案有以下两种:
1.缓存空对象: 代码维护较简单, 但是效果不好
2.布隆过滤器: 代码维护复杂, 效果很好
redis的缓存击穿问题:
指一个key非常热点, 在不停的扛着大并发, 大并发集中对这一个点进行访问, 当这个key在失效的瞬间, 持续的大并发就穿破缓存,直接请求数据库, 瞬间对数据库的访问压力增大
缓存击穿这里强调的是并发, 造成缓存击穿的原因有以下两个:
1.该数据没有人查询过, 第一次就大并发的访问(冷门数据)
2.添加到了缓存, redis有设置数据失效时间, 这条数据刚好失效, 大并发访问(热点数据)
redis的缓存雪崩问题:
指在某一个时间段, 缓存集中过期失效, 此刻无数的请求直接绕开缓存, 直接请求数据库
造成缓存雪崩的原因, 有以下两种:
1.redis宕机
2.大部分数据失效
解决办法:
大多数系统设计者考虑用加锁(最多的解决方案)或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写, 从而避免失效时大量的并发请求落到底层存储系统上. 还有一个简单方案就是将缓存失效时间分散开.
补充: 缓存更新
除了缓存服务器自带的缓存失效策略之外(Redis默认有6种策略), 我们还可以根据具体的业务需求进行自定义的缓存淘汰, 常见的策略有两种:
1.定时取清理过期的缓存 定期删除
2.当有用户请求过来时, 再判断这个请求所用到的缓存是否过期, 过期的话就去底层系统得到新数据并更新缓存. 惰性删除
两者各有优劣, 第一种的缺点是维护大量缓存的key比较麻烦, 第二种的缺点就是每次用户请求过来都要判断缓存失效, 逻辑相对比较复杂! 具体用哪种方案, 大家可以根据自己的应用场景来权衡.
6.Redis的主从复制架构, sentinel哨兵模式
Redis的主从复制架构:
在redis中, 用于可以通过执行SLAVEOF命令或者设置slaveof选项, 让一个服务器去复制(replicate)另一个服务器, 我们称呼被复制的服务器为主服务器(master), 而对主服务器进行复制的服务器被称为从服务器(slave)
sentinel哨兵模式:
sentinel架构是在redis主从复制架构的基础上的
sentinel(哨兵)是redis的高可用性解决方案: 由一个或多个sentinel实例组成的sentinel系统可以监视多个主服务器, 以及这些主服务器属下的所有从服务器, 并在被监视的主服务器进入下线状态时, 自动将下线主服务器属下的某个从服务器升级为新的主服务器
7.memcache与redis的区别
1.存储方式: memcache全存内存, redis存内存, 可持久化到磁盘
2.memcache支持字符串类型, redis支持string, hash, list, set, sorted set
3.redis支持数据备份.(主从复制架构)
8.单线程的redis为什么这么快
1.纯内存操作
2.单线程操作
3.采用了非阻塞的 I/O多路复用机制
9.Redis的过期策略以及内存淘汰机制
Redis的过期策略:
redis采用的是定期删除 + 惰性删除策略.
定期删除: redis默认每100ms检查, 是否有过期的key, 有则删除对应key(随机采样 3/5/10)
惰性删除: 获取某个key时, redis检查这个key是否过期, 过期则删除
内存淘汰机制:
maxmemory-policy: 当内存达到maxmemory时,采用的内存回收策略:
1.volatile-lru: 针对设置了过期时间的key采用lru算法进行回收
2.allkeys-lru: 对所有键采用lru算法进行回收
3.volatile-random: 针对设置了过期时间的键采用随机回收
4.allkeys-random: 对所有键随机回收
5.volatile-ttl: 过期时间最近(TTL最小)的键进行回收
6.noeviction: 不进行任何回收, 对写操作返回错误
关于LRU算法的补充:
大概就是说将Unix中的时间戳经过LRU算法后转换为一种新的时间戳, Redis使用这个新的时间戳来计算过期时间.
想了解更多可查看这篇博客:
Redis底层详解(八) LRU 算法:
https://blog.csdn.net/WhereIsHeroFrom/article/details/86501571
10.Redis为什么是单线程的
redis基于内存的操作, CPU不是Redis的瓶颈, 内存大小或网络带宽是, 且单线程容易实现.
也因为单线程, 所以redis的操作是原子性的, 只支持单行事务
11.有没有尝试进行多机redis的部署? 如何保证数据一致的?
主从复制, 读写分离
一类是主数据库(master) 一类是从数据库(slave), 主数据库可以进行读写操作, 当发生写操作的时候自动将数据同步到从数据库, 而从数据库一般是只读的, 并接收主数据库同步过来的数据.
12.对于大量的请求怎么处理
redis是一个单线程程序, 也就是说同一时刻它只能处理一个客户端请求;
redis是通过IO多路复用来处理多个客户端请求的
想了解更多可查看这篇博客:
redis实现高并发机制的原理及redis运行原理:
https://blog.csdn.net/m0_46459526/article/details/107130908?
13.Redis常见性能问题和解决方案
1.master最好不要做任何持久化工作
2.数据比较重要时, 可在slave开启AOF everysec
3.避免在压力大的主库上增加从库
4.主从复制不要用图状结构, 用单向链表结构更为稳定, 即:master <- slave1 <- slave2 <- slave3…
14.Redis实现分布式锁
Redis中可以使用setnx命令实现分布式锁, 再用expire给锁加一个过期时间防止忘记了释放
将key的值设置为value, 当且仅当key不存在. 若给定的key已经存在, 则setnx不做任何动作
解锁:
使用del key命令就能释放锁
set指令有非常复杂的参数,这个应该是可以同步把setnx和expire合成一个条指令来用.
15.Redis里面有1亿个key, 其中有10w个key是以某个固定的已知的前缀开头的, 如何将他们全部找出来
使用keys pattern指定可以找出指定模式的key列表