1:什么是Redis?
Redis本质上是一个Key-Value类型基于内存的数据库(与Memcached类似),整个操作都是加载在内存中进行的, Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件 。
因为它的操作都是在内存,所以性能非常出色,每秒可以处理10万次读写操作,是已知的性能最快的Key-Value DB。
2:Redis与Memcached的区别?
首先是类型上有所不同,Redis相比Memcached支持存储的类型更多,包括String、List、Set、Hash、Zset。
在单个Value的最大限制Redis是1GB,而Memcached只有1MB
在一些功能上可被成为加强版的Memcached来用。Redis缺点是他本身存储到磁盘当中,所以会受到物理内存的限制,并不能用来做海量高性能读写。
3:Redis为什么把数据存放到内存中?
Redis为了达到最快的读写数据,并通过异步方式将数据存入磁盘。Redis具有快速和持久化数据的特征,数据不放到内存中,磁盘I/O的速度就会影响Redis的性能。(而且现在内存相对来说越来越便宜)
4:Redis作为单线程的数据库,那他为什么这么快?
-
他是完全基于内存的,操作起来会很快。
-
数据结构简单,数据操作也简单,Redis的数据结构是专门设计的。
-
redis基于Reactor模式开发了文件事件处理器(多个Socket、IO多路复用程序、文件事件分派器和事件处理器),IO多路复用程序会监听Socket(多路指的是多个网络连接,复用指公用一个线程),并排成队列,取出Socket同步到事件分派器,事件分派器再把Socket放给所对应的事件处理器。然后IO等事件处理完成后,再次把下一个Socket按顺序进行操作,而事件分派器会根据Socket产生的事件,选择对应的事件处理器处理。
-
使用的底层模型不同,Redis自身构建VM机制,因为一般系统调用系统函数的话,会浪费一些时间去作请求和移动。
-
单线程避免了频繁上下文切换带来的性能问题,不存在加锁释放锁操作,不用考虑死锁带来的性能消耗问题。
5:Redis为什么是单线程?
Redis基于内存操作,CPU不再是Redis的瓶颈了,而且单线程容易实现,所以就选择了单线程的方案。
6:内存碎片是什么?
内存碎片是Redis在分配的过程中或是回收内存时产生的。比如:如果频繁更改数据,而且数据大小相差过大,就可能导致Redis释放的空间在内存中并没有释放,偏偏Redis也没办法全部有效的利用,这就容易形成内存碎片。(内存碎片不会统计在used_memory中)
7:Redis中的数据类型存储方式?
无论是哪种数据类型,Redis都不会直接存储,而是通过RedisObject对象进行存储
8:Redis支持什么语言?
java、C、C#、C++、php、node.js、Go等
9:Redis的并发问题怎么解决?
单线程模式,采用队列模式将并发访问变为串行访问,Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,利用setnx实现锁
10:Redis中的内存模型?
(1)used_memory:Redis分配器分配的内存总量(单位是字节),包括使用的虚拟内存(即swap);Redis分配器后面会介绍。used_memory_human只是显示更友好
(2)used_memory_rss:Redis进程占据操作系统的内存(单位是字节),与top及ps命令看到的值是一致的;除了分配器分配的内存之外,used_memory_rss还包括进程运行本身需要的内存、内存碎片等,但是不包括虚拟内存
(3)mem_fragmentation_ratio: 内存碎片比率,该值是used_memory_rss / used_memory的比值。
一般大于1,且该值越大,内存碎片比例越大。mem_fragmentation_ratio<1,说明Redis使用了虚拟内存 。
(4)mem_allocator**:**Redis使用的内存分配器,在编译时指定;可以是 libc 、jemalloc或者tcmalloc,默认是jemalloc;截图中使用的便是默认的jemalloc。
11:进程本身运行所需要的内存?
Redis 主进程本身运行肯定需要占用内存,如代码、常量池等等;这部分内存大约几M,在大多数生产环境中与 Redis 数据占用的内存相比可以忽略。这部分内存不是由 jemalloc 分配,因此不会统计在 used_memory 中。
12:缓冲内存?
缓冲内存包括客户端缓冲区、复制积压缓冲区、AOF 缓冲区等;其中,客户端缓冲区存储客户端连接的输入输出缓冲;复制积压缓冲区用于部分复制功能;AOF 缓冲区用于在进行 AOF 重写时,保存最近的写入命令。
在了解相应功能之前,不需要知道这些缓冲的细节;这部分内存由 jemalloc 分配,因此会统计在used_memory 中。
13:内存碎片?
内存碎片是 Redis 在分配、回收物理内存过程中产生的。例如,如果对数据的更改频繁,而且数据之间的大小相差很大,可能导致 Redis 释放的空间在物理内存中并没有释放。
但 Redis 又无法有效利用,这就形成了内存碎片,内存碎片不会统计在 used_memory 中
内存碎片的产生与对数据进行的操作、数据的特点等都有关;此外,与使用的内存分配器也有关系:如果内存分配器设计合理,可以尽可能的减少内存碎片的产生。如果 Redis 服务器中的内存碎片已经很大,可以通过安全重启的方式减小内存碎片:因为重启之后,Redis 重新从备份文件中读取数据,在内存中进行重排,为每个数据重新选择合适的内存单元,减小内存碎片。
14:Redis主从复制?
复制是高可用的Redis的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺点:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机限制。
15:Redis哨兵模式?
在复制基础上,哨兵起到了可自动化故障修复。
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。(除了监控Redis服务器时,它们彼此也互相监控)
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机
16:Redis持久化触发条件?
RDB持久化的触发分为手动和自动触发两种。
17:Redis怎样开启AOF?
Redis服务器是默认开启RDB,关闭AOF;若要开启AOF,需要在配置文件中配置:appendonly yes
18:RDB和AOF的有点和缺点?
RDB优点:RDB文件紧凑,体积小,网络传输快,对性能的影响相对较小,适合全量复制;恢复速度比AOF要快。
RDB缺点:RDB文件需要满足特定格式,兼容性差。它的数据快照的持久化方式决定其做不到实时持久化,会导致数据的大量丢失。
AOF优点:AOF支持秒级持久化,兼容性好。
AOF缺点:文件大,恢复速度慢,对性能影响大。
19:为什么需要持久化?
Redis是基于内存的数据库,在服务器运行时,系统会分配一部分内存用来存储数据。这个时候,服务器宕机了,数据库中的数据就会丢失,为了保证即使服务器宕机也能保存数据,就需要持久化将数据从内存保存到磁盘中了。
20:Redis的三种不同的删除策略?
(1)定时删除:在设置键的过期时间的同时,创建一个定时任务,当键达到过期时间时,就立即执行对键的删除操作。
(2)惰性删除:放任键过期不管,但在每次从键空间获取键时,都检查取得的键是否过期,如果过期的话,就删除该键,如果没有过期,就返回键。
(3)定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键,至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。
21:定时删除?
优点:对内存友好,定时删除策略可以保证过期键尽可能快的被删除,并释放过期期间所占用的内存。
缺点:对cpu时间不友好,在过期键比较多时,删除任务会占用很大一部分cpu时间,在内存不紧张但cpu时间紧张的情况下,将cpu时间用在删除和当前任务无关的过期键上,影响服务器的响应时间和吞吐量。
22:定期删除?
由于定时删除会占用太多cpu时间,影响服务器的响应时间和吞吐量以及惰性删除浪费太多内存,有内存泄漏的危险,所以出现一种整合和折中这两种策略的定期删除策略。
(1)定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对cpu时间的影响。
(2)定时删除策略有效的减少了因为过期键带来的内存浪费。
23:惰性删除?
优点:对cpu时间友好,在每次从键空间获取键时进行过期键检查并是否删除,删除目标也仅限当前处理的键,这个策略不会在其他无关的删除任务上花费任何cpu时间。
缺点:对内存不友好,过期键过期也可能不会被删除,导致所占的内存也不会释放。甚至可能会出现内存泄漏的问题。
24:缓存和数据库之间数据一致性问题?
分布式的环境下非常容易出现缓存和数据库之间的数据一致性,如果项目对缓存的要求是强一致性的,那么就不要使用缓存。需要采取合适的策略降低缓存和数据库之间的数据不一致的概率,从而无法保证两者间的强一致性。合适的策略包括,合适的缓存更新策略,更新数据库后要及时更新缓存、缓存失败时增加重试机制,如MQ的消息队列。
25:缓存雪崩问题?
在同一时间有大量的键过期或是失效,接下来的大量请求在这一时间都放在了数据库导致数据库宕机。
解决方法:
(1)如同解决缓存穿透一样加锁排队。
(2)让Redis中的Key永不失效,这样也就有效的避免了大量缓存失效的问题,但随之而来的是Redis需要分配更多的存储空间。
(3)建立备份缓存,在缓存A与B之间,让其中一个设置超时时间,另一个不设置,读取缓存时先从A读取,如果A没有则读取B,同时更新缓存A与B。
26:常见的缓存策略?
(1)Cache-Aside
(2)Read-Through
(3)Write-Through
(4)Write-Behind
27:读写分离?
将数据库分成主从库,一个主库用来写数据,多个从库完成读数据的操作,通过某种机制进行数据同步。为避免Master DB的单点故障,集群一般会采用两台Master DB做双机热备,所以整个集群的读写的可用性非常高。
读写分离缺陷在于,不论Master还是Slave,各个节点都需要保存完整的数据,如果数据量很大,集群扩展性还是会受限于单个节点的存储能力。
28:Redis的通讯协议?
RESP是Redis客户端和服务端之前使用的一种通讯协议;RESP特点:实现比较简单,可以做到快速解析,可读性好。
29:Redis管道Pipeline?
在一些场景下我们在一次操作中可能需要执行多个命令,而我们如果知识一个一个的命令去执行就会浪费网络消耗时间,如果将命令一次性传输到Redis中去执行,就会减少很多时间。但是需要注意的是Pipeline并不是原子性执行的,也就是说管道中的命令到达Redis服务器的时候可能会被其他命令穿插。
30:数据分片模型?
数据分片模型是为了解决读写分离模型的缺陷,可以采用的模型。他是可以将每个节点分别看成独立的Master,随后通过业务实现数据分片。
这两种模型,可以将每个Master设计成由一个Master和多个Slave组成的模型
31:布隆过滤器(bloomfilter)?
类似于一个hash set ,用来快速判断一个元素是否存在某个集合中,典型应用场景是快速判断某个key是否存在某容器,不存在直接返回。布隆过滤器关键就在于hash的算法和容器的大小
32:布隆过滤器优缺点?
优点:二进制组成的数组,占用内存空间极少,插入和查询速度快。
缺点:随着数据的增加,误判率会增加;另外还有一点重要的缺陷,他无法删除数据。
总结:布隆过滤器可以判断某个数据一定不存在,但是没有办法判断数据是一定存在的(因其是不同数据通过hash算出来的结果,会有重复值)。