1、Redis为什么快?
1、纯内存操作
2、单线程可以省去多线程时CPU上下文会切换的时间
3、渐进式ReHash、缓存时间戳
数组需要扩容的时候,他会维护两张hash表,比如第一张的数组长度为6,另一张的数组长度为12,在set和get的时候他只会把这一个节点的数据hash到长度为12的表中。
Redis用到时间的时候不会使用Thread.currentTimeMiles()方法,这个会方法会调用操作系统,比较耗时,Redis会把时间缓存到内存中。
2、Redis合适的应用场景?
1、分布式缓存
2、分布式锁
3、计数器
4、排行榜(使用有序集合ZSet)
3、Redis6.0之前为什么一直不使用多线程?
1、使用Redis、CPU 不是瓶颈,受制 内存、网络
2、提高Redis, Pipeline(命令批量) 每秒100万个请求
3、单线程,内部维护比较低
4、如果是多线程(线程切换、加锁\解锁、导致死锁问题)
5、惰性Rehash(渐进性式的Rehash)
所以,一般的公司,单线程Redis 就够了。
4、Redis6.0为什么要引入多线程?
1、Redis服务器可以处理8万到10万 QPS,对于80%的公司来说,单线程的Redis已经足够使用。
2、提高Redis, Pipeline(命令批量) 每秒100万个请求
3、但随着越来越复杂的业务场景,有些公司动不动就上亿的交易量,因此需要更大的QPS。
4、常见的解决方案是在分布式架构中对数据进行分区并采用多个服务器,有非常大的缺陷:
管理的Redis服务器太多,维护代价大
某些适用于单个Redis服务器的命令不适用于数据分区
数据分区无法解决热点读/写问题
5、指的是IO的多线程(内部执行命令还是单线程)
多线程任务 分摊到 Redis 同步IO中读写 负载。
相当于多核服务器,一个核来处理IO操作。
5、Redis有哪些高级功能?
Redis的慢查询
许多存储系统(例如 MySQL)提供慢查询日志帮助开发和运维人员定位系统存在的慢操作。所谓慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设调值,就将这条命令的相关信息(例如:发生时间,耗时,命令的详细信息)记录下来,Redis也提供了类似的功能。
Pipeline 批量处理
事务、
数据持久化(RDB和AOF)、
使用哨兵实现集群、
分布式锁
6、为什么要用Redis?
为了高性能、高并发。
7、Redis与memcached相对有哪些优势?
Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象)。
8、怎么理解Redis中事务?
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令之间。
multi 命令代表事务开始,exec命令代表事务结束。另外discard命令是回滚。
注意:
1、Redis的事务功能很弱。在事务回滚机制上,Redis只能对基本的语法错误进行判断。
2、运行时错误
例如:事务内第一个命令简单的设置一个string类型,第二个对这个key进行sadd命令,这种就是运行时命令错误,因为语法是正确的:
可以看到Redis并不支持回滚功能,第一个set命令已经执行成功,需要自己手动修复这类问题。
9、Redis的过期策略以及内存淘汰机制?
redis采用的是 定期删除+惰性删除 策略。
1、为什么不用定时删除策略?
定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU
资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.
2、定期删除 + 惰性删除是如何工作的呢?
定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis
不是每个100ms将所有的key检查一次,而是随机抽取进行检查,如果这块区域超过25%过期,会
对这块区域再次进行删除。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。 于
是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置
了过期时间那么是否过期了?如果过期了此时就会删除。
10、什么是缓存穿透?如何避免?
缓存穿透:指查询一个不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。
解决方案:
1.查询返回的数据为空,仍把这个空结果null进行缓存,但过期时间会比较短;
2.布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对 DB 的查询。
11、什么是缓存雪崩?如何避免?
缓存雪崩:设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到
DB,DB 瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多 key,击穿是某一个key 缓存。
12、使用Redis如何设计分布式锁?
基于 Redis 实现的分布式锁,使用到的是 SETNX 命令,有可能会出现死锁现象,锁过期时间不好评估,如果key的过期时间太短,拿到锁的线程还没有执行完业务流程,其他的线程就再次拿到锁了,如果key的过期时间太长,拿到锁的线程如果发生了异常,其他的线程就必须要等锁过期了才能拿到锁,这时候就需要我们开启一 个「守护线程」,定时去检测这个锁的失效时间,如果锁快要过期了,操作共享资源还末完成,那么就自动对锁进行 「续期」,重新设置过期时间。这个守护线程我们一般也把它叫做「看门狗」线程。
13、什么是bigkey?会有什么影响?
1、bigkey是指key对应的value所占的内存空间比较大。
如果按照数据结构来细分的话,一般分为字符串类型bigkey和非字符串类型bigkey。
字符串类型:体现在单个value值很大,一般认为超过10KB就是bigkey
非字符串类型:哈希、列表、集合、有序集合,体现在元素个数过多。
2、bigkey的危害体现在三个方面:
内存空间不均匀
操作bigkey比较耗时
网络拥塞:每次获取bigkey产生的网络流量较大
3、如何发现bigkey
可以通过redis-cli--bigkeys命令统计bigkey的分布。
14、Redis如何解决key冲突?
1、业务隔离。
2、通过添加前缀的方式对key进行设计。
3、“Redis 并发竞争” 问题就是高并发写同一个key时导致的值错误。
常用的解决方法:
- 乐观锁,
watch
命令可以方便的实现乐观锁。注意不要在分片集群中使用。 - 分布式锁,适合分布式系统环境,分布式锁的实现方式很多,比如 ZooKeeper、Redis 等
- 时间戳,适合有序场景
- 消息队列,在并发量很大的情况下,可以通过消息队列进行串行化处理
15、怎么提高缓存命中率?
1、缓存预加载(预热)
2、增加缓存的存储空间,提高缓存的数据、提高命中率
3、调整缓存的存储类型
4、提升缓存的更新频次
16、Redis持久化方式有哪些?有什么区别?
我们一般采用RDB、AOF、混合持久化。
RDB的优缺点:
优点:RDB持久化文件,速度比较快,而且存储的是一个二进制文件,传输起来很方便。
缺点:RDB无法保证数据的绝对安全,有时候就是1s也会有很大的数据丢失。
AOF的优缺点:
优点:AOF相对RDB更加安全,一般不会有数据的丢失或者很少,官方推荐同时开启AOF和RDB。
缺点:AOF持久化的速度,相对于RDB较慢,存储的是一个文本文件,到了后期文件会比较大,传输困难。
17、为什么Redis需要把所有数据放到内存中?
Redis为了达到最快的读写速度,将数据都读到内存中,并通过异步的方式将数据写入磁盘,所以Redis
具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响Redis的性能。
18、如何保证缓存与数据库双写时的数据一致性
第一种方案:采用延时双删策略
具体的步骤就是:
先删除缓存;
再写数据库;
休眠500毫秒;
再次删除缓存。
第二种方案:异步更新缓存(基于订阅binlog的同步机制)
技术整体思路:
MySQL binlog增量订阅消费+消息队列+增量数据更新到redis