当前位置: 首页 > 后端技术 > Java

面试前一定要看懂32道Redis面试题解析,Redis主从复制+缓存+分布式+集群

时间:2023-04-02 02:07:55 Java

就我个人而言,我觉得Redis的基本使用是每个Java程序员都应该知道的.如果你需要面试,你也必须了解和掌握Redis主从复制+缓存+分布+集群的一些问题,不过我帮你找到了大厂的面试原题。相信看过这32道Redis面试题解读的你,会对redis有更深入的了解,应对面试官的问题也会更加得心应手。我把redis相关的一些学习笔记和面试题整理成了文档。需要的可以直接【点此】获取~1.什么是Redis?它主要用来做什么?Redis,英文全称RemoteDictionaryServer(远程词典服务),是一个用ANSIC语言编写的开源,支持网络,可以基于内存或持久化日志类型,Key-Value数据库,并提供多种API语言。与MySQL数据库不同,Redis数据存储在内存中。它的读写速度非常快,每秒可以处理超过100,000次读写操作。因此,redis在缓存方面被广泛使用。此外,Redis也经常被用作分布式锁。此外,Redis支持事务、持久化、LUA脚本、LRU驱动的事件和多集群解决方案。2、说说Redis的基本数据结构类型大多数朋友都知道Redis有以下五种基本类型:String(字符串)Hash(散列)List(列表)Set(集合)zset(有序集合)它还有三种特殊数据结构类型GeospatialHyperloglogBitmap3。为什么Redis这么快?4、缓存和数据库的数据一致性问题在分布式环境下(更不用说单机),很容易出现缓存和数据库的数据一致性问题。如果要求是强一致性,那么请不要使用缓存。我们只能采取适当的策略来降低缓存和数据库之间数据不一致的概率,但不能保证两者之间的强一致性。适当的策略包括适当的缓存更新策略。更新数据库后,要及时更新缓存,缓存失效时要加入重试机制,比如MQ方式的消息队列。5.BloomfilterBloomfilter类似于哈希集合,用于快速判断集合中是否存在某个元素。它的典型应用场景是快速判断某个key在容器中是否存在,不存在则直接返回。布隆过滤器的关键在于散列算法和容器的大小。6、缓存雪崩问题有大量key同时过期(失效),然后一大波请求瞬间落入数据库,造成连接异常。解决方法:也像解决缓存穿透一样加锁和排队。创建备份缓存,缓存A和缓存B,A设置超时时间,B不设置超时时间,先从A读取缓存,A不读取B,同时更新A缓存和B缓存;7.缓存并发问题这里的并发指针问题是多个redis客户端同时设置key导致的并发问题。更有效的方案是将redis.set操作放到队列中序列化。一定要一一执行,具体代码就不上传了。当然,锁定也是可能的。至于为什么不使用redis中的事务,留给评委们自己去想吧。8、Redis分布式redis支持主从模式。原理:Master会同步数据给slave,slave不会同步数据给master。当slave启动时,它会连接到master同步数据。这是一个典型的分布式读写分离模型。我们可以使用master插入数据,slave提供检索服务。这样可以有效降低单机的并发访问数。9.读写分离模型通过增加SlaveDB的数量,可以线性提升读性能。为了避免MasterDB的单点故障,集群一般采用两台MasterDB进行双机热备,因此整个集群的读写可用性非常高。读写分离架构的缺点是,无论是Master还是Slave,每个节点都必须保存完整的数据。如果数据量很大,集群的可扩展性仍然受限于单个节点的存储容量,而对于写入密集型应用,读写分离架构并不适用。10.数据分片模型为了解决读写分离模型的缺陷,可以应用数据分片模型。每个节点都可以看做一个独立的master,然后通过业务实现数据分片。结合以上两种模型,可以将每个master设计为一个master和多个slave组成的模型。11、Redis常见性能问题及解决方法:Master最好不要做任何持久化的工作,比如RDB内存快照、AOF日志文件等。从复制的速度和连接的稳定性来说,Master和Slave最好避免在同一个局域网内高压下从库添加到主库。通信协议;RESP的特点:实现简单,分析速度快,可读性好13.Redis分布式锁实现首先使用setnx来竞争锁,然后使用expire给锁加一个过期时间,防止锁被遗忘释放。如果在setnx之后执行expire之前进程意外崩溃或者需要重启维护怎么办?set命令的参数非常复杂,所以应该可以把setnx和expire同时合并成一个命令!14.为什么Redis是单线程的?Redis是基于内存的操作。CPU不是Redis的瓶颈。Redis的瓶颈很可能是机器内存或网络带宽的大小。由于单线程容易实现,而且CPU也不会成为瓶颈,所以采用单线程方案顺理成章(毕竟多线程会带来很多麻烦!)。15.Redisinfo查看命令:infomemory16.Redis内存模型used_memory:Redis分配器分配的内存总量(以字节为单位),包括使用的虚拟内存(即swap);Redis分配器将在后面介绍。used_memory_human只是显示得更友好。used_memory_rss:Redis进程占用操作系统的内存(以字节为单位),与top和ps命令看到的值一致;used_memory_rss除了allocator分配的内存外,还包括进程本身需要的内存和内存碎片等,但不包括虚拟内存。mem_fragmentation_ratio:内存碎片率,这个值是used_memory_rss/used_memory的比值。mem_allocator:Redis使用的内存分配器,编译时指定;可以是libc、jemalloc或tcmalloc,默认是jemalloc;屏幕截图中使用了默认的jemalloc。17、Redis内存划分数据作为数据库,数据是最重要的部分;这部分占用的内存会被计入used_memory。进程本身运行所需的内存Redis主进程本身必须占用内存,如代码、常量池等;这部分内存大约有几兆,与大多数生产环境中Redis数据占用的内存相比,可以忽略不计。这部分内存不是jemalloc分配的,所以不会算在used_memory中。缓冲内存缓冲内存包括客户端缓冲区、复制积压缓冲区、AOF缓冲区等,其中客户端缓冲区存放客户端连接的输入输出缓冲区;复制积压缓冲区用于部分复制功能;AOF缓冲区用于正在进行的AOF重写时,保存最近的写入命令。在了解相应的功能之前,您无需了解这些缓冲区的详细信息;这部分内存是jemalloc分配的,所以会算在used_memory里。内存碎片内存碎片是Redis在分配和回收物理内存的过程中产生的。比如数据频繁变化,数据大小相差较大,redis释放的空间可能在物理内存中释放不完,redis却不能得到有效利用,形成内存碎片。内存碎片不会计入used_memory。18.Redis对象有5种类型。不管是哪种类型,Redis都不会直接存储,而是通过redisObject对象存储。19、Redis不直接使用C字符串(即以空字符'\0'结尾的字符数组)作为默认的字符串表示,而是使用SDS。SDS是SimpleDynamicString的缩写。20、Reidis的SDS在C字符串的基础上增加了free和len字段21、Reids主从复制复制是Redis高可用的基础,哨兵和集群都是基于复制来实现高可用的。Replication主要实现数据的多机备份,以及读操作的负载均衡和简单的故障恢复。缺陷:故障恢复不能自动化;写操作不能负载均衡;存储容量受限于单机。22、RedisSentinel在复制的基础上实现故障自动恢复。缺陷:写操作不能负载均衡;存储容量受限于单机。23、MySQL有2000万条数据,redis只有20万条数据。如何保证redis中的数据都是热数据?当redis内存数据集的大小上升到一定大小时,就会执行数据淘汰策略。24、Redis适用于哪些场景?(1)、会话缓存(SessionCache)使用Redis最常用的场景就是会话缓存(sessioncache)。使用Redis缓存会话相对于其他存储(例如Memcached)的优势在于Redis提供了持久性。当维护一个不严格一致的缓存时,如果用户的所有购物车信息都丢失了,大多数人都会不高兴。现在,他们会吗?幸运的是,随着Redis多年来的改进,很容易找到有关如何正确使用Redis进行会话缓存的文档。甚至著名的商业平台Magento也为Redis提供了一个插件。(2)、FullPageCache(FPC)除了基本的sessiontoken,Redis还提供了一个非常简单的FPC平台。回到一致性问题,即使Redis实例重启,用户也不会因为磁盘持久化而看到页面加载速度下降。这是一个很大的改进,类似于PHP的本地FPC。再次以Magento为例,Magento提供了一个插件来使用Redis作为全页缓存后端。另外,对于WordPress用户,Pantheon有一个非常不错的插件wp-redis,可以帮助你以最快的速度加载你访问过的页面。(3)、QueueReids在内存存储引擎领域的优势之一是它提供了list和set操作,这使得Redis成为一个很好用的消息队列平台。Redis作为队列的操作类似于本地编程语言(如Python)对列表的push/pop操作。如果您在Google上快速搜索“Redis队列”,您会立即找到大量旨在使用Redis创建非常好的后端工具以满足各种队列需求的开源项目。比如Celery有后台使用Redis作为broker,可以从这里查看。(4)、排行榜/计数器Redis非常擅长在内存中递增或递减数字。Sets和SortedSets也让我们执行这些操作变得非常简单。Redis只是提供了这两种数据结构。所以,我们想要从排序的集合中得到前10名的用户——我们称之为“user_scores”,我们只需要这样做:当然,这假设你是根据你的用户的分数进行增量排序。如果你想返回用户和用户的分数,你需要这样执行:ZRANGEuser_scores010WHITSCORESAAgoraGames是一个很好的例子,用Ruby实现,它的排行榜使用Redis存储数据,你可以在这里看到.(5)、Publish/SubscribeLast(但肯定不是最不重要的)是Redis的发布/订阅特性。发布/订阅确实有很多用例。我见过人们在社交网络连接中使用它,作为基于发布/订阅的脚本的触发器,甚至使用Redis的发布/订阅功能来构建聊天系统!(不是,是真的,你可以去查一下)。26.一个Redis实例最多可以存储多少个key?List、Set、SortedSet最多可以存储多少个元素?理论上,Redis最多可以处理232个键,并在实践中进行了测试。每个实例至少存储2.5亿个密钥。我们正在测试一些更大的值。任何列表、集合和有序集合都可以容纳232个元素。换句话说,Redis的存储限制是系统中可用的内存量。27.Redis常见性能问题及解决方法?(1)Master最好不要做任何持久化的工作,比如RDB内存快照,AOF日志文件(2)如果数据比较重要,一个Slave启动AOF备份数据,策略设置为同步一次persecond(3)对于master-slave为了复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内(4)尽量避免在master库中添加从库高压下(5)主从复制不要使用图结构,使用单向链表结构更稳定,即:Master<-Slave1<-Slave2<-Slave3...这种结构方便求解单点故障问题,实现Slave到Master的更替。如果Master挂掉了,可以马上让Slave1成为Master,其他不变。28、Redis提供了哪几种持久化方式?RDB持久化方法可以在指定的时间间隔存储数据的快照。AOF持久化方式记录每一次对服务器的写操作。当服务器重新启动时,这些命令将被重新执行以恢复原始数据。AOF命令使用redis协议将每次写操作追加保存到文件末尾。Redis还可以在后台重写AOF文件,这样AOF文件的体积就不会太大。如果你只想让你的数据在服务器运行时存在,你也可以不使用任何持久化方法。您还可以同时启用两种持久化方法。这样的话,当redis重启的时候,会先加载AOF文件来恢复原来的数据,因为一般情况下AOF文件保存的数据集比RDB文件保存的数据集更完整。最重要的是理解RDB和AOF持久化方式的区别。让我们从RDB持久化方法开始。29.如何选择合适的持久化方式?一般来说,如果想达到媲美PostgreSQL的数据安全性,应该同时使用这两种持久化功能。如果你真的很在意你的数据,但仍然可以容忍数据在几分钟内丢失,那么你可以使用RDB持久化。很多用户只使用AOF持久化,但是不推荐这种方式:因为定期生成RDB快照(snapshot)对于数据库备份非常方便,而且RDB恢复数据集的速度也比AOF恢复快,除了另外,使用RDB也可以避免前面提到的AOF程序的bug。30、修改配置是否会在不重启Redis的情况下实时生效?对于正在运行的实例,有许多配置选项可以通过CONFIGSET命令修改,而无需执行任何形式的重启。从Redis2.2开始,可以在不重启Redis的情况下,从AOF切换到RDB的快照持久化等方式。搜索“CONFIGGET*”命令以获取更多信息。但偶尔需要重启,比如将Redis程序升级到新版本,或者需要修改一些CONFIG命令目前不支持的配置参数。31、Redis与memcached相比有什么优势?1、memcached的所有值都是简单的字符串。Redis作为其替代者,支持更丰富的数据类型。2.Redis比memcached快很多。Redis比memcached快得多。3、Redis可以持久化它的数据Redis可以持久化它的数据32、Redis集群方案在什么情况下会导致整个集群不可用?在一个有A、B、C三个节点的集群中,如果没有复制模型,如果B节点出现故障,整个集群会认为它缺少5501-11000范围内的slot,不可用。