一、什么是redis?有哪些数据类型?
1.redis介绍
本质上是一个Key-Value类型的内存数据库,单个Value的最大限制是1GB。
其具有内存存储、单线程模式、持久化支持、分布式部署、高性能、高可用等特点。
2.数据类型
String、List、Hash、Set、ZSet(有序集合sorted set,每个元素关联一个分数score,适用于排行榜等)
二、redis提供了哪几种持久化方式
1.RDF
定义:
将Redis的内存中的数据定期保存到磁盘上,以防止数据在Redis进程异常退出或服务器断电等情况下丢失。
优点:
快照文件小、恢复速度快
缺点:
定期更新可能会丢数据
2.AOF
定义:
将Redis的所有写操作追加到AOF文件的未尾,从而记录了Redis服务器运行期间所有修改操作的详细记录。当Redis重新启动时,可以通过AOF文件来恢复数据。(如果redis刚执行了写操作,但还未写入AOF文件就宕机了,那可能导致该操作内容丢失)
优点:
相对RDF而言更可靠、粒度更细
缺点:
文件大、恢复速度较慢、且每次写操作都需要写磁盘导致负载较高
3.混合持久化
定义:
redis4.0之后,推出了RDF-AOF混合版本,AOF 重写时会把 Redis 的持久化数据以 RDB 的格式写入到 AOF 文件的开头,之后的数据再以 AOF 的格式追加的文件的未尾。
优点:
更可靠
缺点:
AOF文件可读性差、版本兼容问题
三、redis为什么快
1.完全基于内存
2.数据结构简单
3.采用单线程,避免了不必要的上下文切换和锁问题
4.使用多路I/O复用模型
5.使用底层模型不同,重构了VM 机制
四、redis为什么采用单线程
1.完全基于内存
2.CPU不是redis的瓶颈,机器内存和网络才是,所以采用单现场,也可以避免上下文切换和锁问题。
五、redis怎么保证原子性的
通过单线程保证原子性
批量操作通过事务保证原子性
多个命令在并发中也是原子性的吗?
不一定,通过事务、Redis+Lua等方式实现
六、redis服务器的内存是多大
可自行设置,默认是(32位 - 3G、64位 - 不受限制),一般推荐设置为最大物理内存的四分之三
七、redis是否支持事务
支持,用于保证批量操作的原子性,用MULTI(事务的开始)和EXEC(事务的结束)命令控制。
redis事务不支持回滚
八、使用redis作为缓存,如何保证redis和mysql数据库的数据一致性
本质就是通过删除缓存 ,来避免因为并发等操作导致缓存和数据库数据不一致的问题,比如线程A更新了数据库数据,但线程B查询到的还是更新前的旧数据 并存储到了 redis。
1.延时双删策略
删除缓存 -> 写入数据库 -> 休眠 X ms -> 删除缓存
延时休眠是为了保证 其他线程的请求 + 主从同步 已经结束
2.设置过期时间
3.兜底方案
延时双删策略仍存在风险 ,比如缓存删除失败等。而过期时间虽然可以兜底,但是可能存在较长时间差,所以最好建立一个兜底方案。
缓存删除失败的话,通过消息队列对相关key再次进行删除。
4.最终方案(延时双删 + 过期时间 + binlog【用于降低业务代码入侵,新启服务订阅binlog】 + 消息队列)
删除缓存 -> 写入数据库 -> 写一个订阅服务,拉取binlog,获取相关信息和key -> 删除缓存 -> 删除时候的话,发送消息队列 -> 再次删除缓存
九、缓存击穿、缓存穿透、缓存雪崩的原因和解决方案
1.缓存击穿
原因:
查询一个不存在的数据,缓存无法命中,将去数据库查询,数据库也查不到,也没有在redis中存入null,这导致不存在的数据每次都要去存储层去查询,如果有人用不存在的数据恶意攻击,可能导致数据库cpu飙升、数据库挂掉等情况。
解决:
1.对空结果也进行缓存计入,value存入null即可
2.使用redisson的布隆过滤器
2.缓存穿透
原因:
对于"热点"数据,当其即将要被大批量并发访问时 失效了,就会导致这些大量的请求打入数据库。
解决:
分布式环境下,使用分布式锁来限制数据库的请求量(redis锁或者zookeeper锁)
3.缓存雪崩
原因:
高并发情况下,大量缓存失效时间重复,导致同一时间大量请求进入数据库,数据库压力过大雪崩
解决:
过期时间在业务接受的时效内采用随机数
十、什么是哨兵模式?工作原理是什么?
1.哨兵模式
Redis 的自动故障转移系统,当 Master异常时进行的Master-Slave切换
2.工作原理
哨兵节点发送ping命令 -> 单节点确认主观下线状态 -> 其他节点核查状态,无误则标记为客观下线状态 -> 选领头哨兵(Raft算法) -> 选新节点并进行切换 -> 旧主恢复后切回
1.哨兵节点(Sentinel)以每秒一次 的频率向所有主从节点发送 PING 命令
2.如果节点在规定时间内(down-after-milliseconds )未回复,哨兵主观认为该节点主管下线
3.当有一个master被标记为主观下线后,监视这个master的所有哨兵节点都以每秒一次的频率进行确认
4.当足够数量的哨兵节点确认成功后,master被标记为客观下线
5.哨兵节点每秒向被客观下线的master的所有slave发送info命令,确认状态信息(一般清苦10秒发送一次info命令)
6.通过Raft算法选出领头哨兵
7.领头哨兵选出新主节点并执行切换
8.旧主节点恢复后切换回来(若没有足够的哨兵节点同意master下线,则移除其客观下线状态、若master重新回复ping命令,则移除其主观下线状态)
十一、如何确保redis里的数据都是"热点"数据【内存淘汰策略】
1.noeviction:不会淘汰任何键值对,而是直接返回错误信息。
2.allkeys-lru:从所有 key 中选择最近最少使用的那个 key 并删除:【redis作为缓存时推荐使用】
3.volatile-lru:从设置了过期时间的 key 中选择最近最少使用的那个 key 并删除。【redis作为半缓存半持久化时推荐使用】
4.allkeys-random:从所有 key 中随机选择一个 key 并删除。
5.volatile-random:从设置了过期时间的 key 中随机选择一个 key 并删除。
6.volatile-ttl:从设置了过期时间的 key 中选择剩余时间最短的 key 并删除。
7.volatile-lfu:淘汰的对象是带有过期时间的键值对中,访问频率最低的那个。
8.allkeys-lfu:淘汰的对象则是所有键值对中,访问频率最低的那个。
十二、redis自带的集群模式有哪些
主从、哨兵、Cluster
十三、redis集群方案有哪些
1.twemproxy
代理方式 ,twemproxy以代理的身份接收请求并使用一致性hash算法,将请求转接到redis,redis再将结果返回给twemproxy。(实际使用只需要修改连接端口即可)
存在【节点数量改变时 数据无法自动转移到新节点】的问题
2.codis【目前最常用】
twemproxy的基础上解决了数据自动转移问题,旧节点数据可恢复到新节点
3.redis cluster3.0自带集群【最新】
不再采用一致性hash,而是hash槽
4.自主实现
自己在业务代码层通过创建redis实例、对key进行hash计算去实现
十四、什么是redis的哈希槽
Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
十五、项目中redis的使用
1.缓存,存储热点数据,减少数据库交互,提高效率
2.分布式锁,比如解决缓存击穿问题
3.消息队列,基于redis的发布-订阅功能
4.放并发
5.限流
6.排行榜
7.计数器
9.会话缓存
10.全页缓存
十六、redis常见的性能问题和解决方案
1.Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
2.如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
3.为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
4.尽量避免在压力很大的主库上增加从库
5.主从复制不要用图状结构,用单向链表结构更为稳定,便于替换,即:Master <- Slave1 <- Slave2 <- Slave3...