redis
1. redis和memcache的区别
redis | memcache | |
---|---|---|
存储方式 | 支持持久化,可以存储到硬盘上,掉电不丢失 | 只能在内存中,掉电会丢失 |
支持的数据类型 | hash(存储对象),zset(存储热点信息,带分数值),list,set | 简单的string |
底层模型 | redis建立了自己的vm机制,因为一般的系统调用系统函数会浪费一定的时间 | |
value值 | redis最大可以达到1gb | 最大只能1mb |
速度 | 快 | 慢 |
备份 | 支持数据备份 | |
2. 使用redis有哪些好处
- 速度快,因为数据存储在内存中
- 支持丰富的数据类型
- 支持事务,操作都是原子性,所谓原子性就是操作要么都执行,要么都不执行
- 作用丰富:可用于缓存,消息,按照key设置过期时间,过期后将自动删除
3. 什么是redis的持久化?rdb和aof的比较?
持久化就是将数据从内存中写入到硬盘上,防止因为服务器的宕机而导致数据的丢失
aof | rdb |
---|---|
更新频率高 | 性能好 |
安全性大 | |
优先使用aof还原数据,如果都配备,有限加载aof |
4. redis最适合的场景?
-
会话缓存
最常用的场景。用redis缓存会比其他存储的优势在于redis支持持久化 -
全页缓存
即使重启redis,因为有磁盘的持久化机制,用户也不会看到页面加载速度的下降 -
队列
redis提供list和set操作,这使得redis能作为一个很好的消息队列平台来使用,
-
排行榜/计数器
redis在内存中对数字的递增或递减的操作都非常容易实现,集合set和有序集合zset是的我们在执行这些操作的时候变得非常简单
-
发布,订阅功能
5. redis哈希槽的概念
redis集群没有使用一致性hash,而是引入了hash槽的概念,集群有16384个哈希槽,散布在不同的服务器上。每个key通过对16384取模后来决定放置在那个槽里。
6. 怎么理解redis事务
事务是一个单独的隔离操作,事务中所有的命令都会被序列化,然后按照顺序执行。事务在执行过程中,不会被其他客户端发来的命令打断。
事务是一个原子操作,事务中的命令要么全部被执行,要么全部不执行。
7. redis的淘汰策略
redis设置有过期策略:
定期删除:
redis会定期扫描设置了失效时间的key,如果扫描到的key过期了就删除,这是一种批量处理的方式
惰性删除:
当你主动查询到一个key,redis对其进行检查,发现过期,就删除。
基于以上,仍旧会有过期的key存在,仍然有漏网之鱼。于是在你真正需要存储的时候,发现满了,这时候就需要淘汰策略来处理
redis淘汰策略:
- noeviction:内存满了就报个错,不会驱逐任何键。
- allkeys-lru:加入键的时候,如果达到上限,首先通过lru算法尝试回收最少使用的键
- volatile-lru:尝试回收最少使用的键,但仅限于过期集合里面的键
- allkeys-random:从所有的键中随机删除
- volatile-random:从所有过期的键中随机删除
- volatile-ttl:将过期集合中的键回收掉,并且优先回收存活时间(ttl)较短的键
8. redis有哪些数据结构
string 普通键值对
hash 存储map 对象
list 有序集合 作为消息队列使用
set 无序集合 去重 取交集 并集
zset 有排名集合 根据积分进行排序 主要用于热搜,排名
9. redis的缓存穿透、缓存雪崩、缓存击穿
1. 缓存穿透
穿过redis去mysql查询,简单来说,就是redis里面没有缓存,此时你要去数据库查询,但是查询数据库中不存在的数据,每次都要穿过redis去数据库查询。此时相当于缓存失效,会大大增加数据库的压力,
假如查询id=1000的student,mysql数据库中并没有该数据,则不会再redis中缓存;下次再去查询,仍旧会经过redis。
怎么办?
- **id自增:**根据id查询时,如果id是自增,将id的最大值放到redis中,在查询数据库之前,直接比较一下id。
- **id不是自增:**将所有的id存放到set中,在查询数据库之前看一下有没有,如果有,再去数据库查询,如果没有就拦截掉
- 使用布隆过滤器,作用等价于set,功能就是可以判断当前查询的id是否存在,适合海量数据。
- **IP限制,黑名单机制:**获取客户端的ip地址,将IP访问添加限制
2 缓存击穿
缓存中的数据失效,用户不得不去数据库查询
redis缓存失效的原因:key到期;执行增删改,此时用户需要去数据库查询,对于mysql并没有影响。
假如1W个key同时失效,用户都要去数据库查询,则mysql的压力骤增,响应时长会降低,查询速度变慢, Tomcat每个接口响应速度也会变慢,但是用户的请求并没有降低,Tomcat的连接数越来越多,持续一段时间后,Tomcat因为连接数过多而挂掉,此时发生了雪崩(缓存击穿多了,引起了雪崩)
解决方案:
- 失效时间拉长一点
- 将key的失效时间分开,不要集中在一起
- 如果查询的key一样,加一个分布式锁,让并发变成串行查询数据库
雪崩就是因为mysql响应时间过长,造成Tomcat请求响应堆积,可能造成Tomcat连接数和内存不够用,
10 redis如何实现高并发
redis通过一主多从,一个主节点负责写,多个从节点负责读,读写分离从而实现高并发
11. redis如何实现高可靠
- 主从切换
主机负责读写,从机负责读,如果主机挂掉,需要手动切换从机上位,且内存有限 - 哨兵集群,主节点宕机的情况下,哨兵们从所有的从节点中选出一个主节点,从而保证了redis集群的高可用,优点:自动切换主机,不需要人工干预;缺点:主机的容量限定了集群的大小
- 去中心化模式
三猪三从,16384个哈希槽散布在三台主机上,主机可以接受读写,从机负责读,主机挂掉,从机自动上位,变为主机,如果从机也挂了,则集群挂掉。
特点:- 方便扩容,内存岁主机数量的增加而成倍增加
- 主机挂掉从机自动上位,可以实现高可靠
12. redis单线程还能处理速度那么快?
- redis基于内存运行,内存读写速度快
- redis的单线程模式避免了频繁切换线程的损耗
- redis采用IO多路复用技术,可以很好地解决多请求并发的问题,对多路代表多个请求,复用表示多个请求重复使用同一个线程
13. 为什么redis的操作是原子性的,怎么保证原子性
对于redis而言,命令的原子性是指:一个操作不可拆分,操作要么执行,要么不执行。
redis的操作之所以是原子性的,是因为redis是单线程的
redis本身提供的所有API都是院子操作,redis中的事务其实是要保证批量操作的原子性
多个命令在并发中也是原子性的吗?
不一定。
14. redis的主从复制的实现过程?
- 从服务器发送一个sync同步命令给主服务器要求全量同步
- 主服务器接收到从服务器的sync同步命令时,会fork一个子进程后台执行bgsave命令快照保存,生成rdb文件,并将rdn文件发送给从服务
- 从服务再将接收到的rdb文件载入到自己的redis内存
- 待从服务将rdn载入完成后,主服务再将缓冲区所有命令发送给从从服务
- 从服务在将主服务所有的写命令载入内存从而实现数据的完全同步
- 从服务下次在需要同步数据时只要发送自己的offset位置即可,只同步新增加的数据,而不再需要全量同步。