发布网友 发布时间:2024-09-27 06:32
共1个回答
热心网友 时间:2024-10-02 01:12
就我个人而言,我觉得Redis的基本使用是我们每个Java程序员都应该会的。如果需要面试的话,一些关于Redis的主从复制+缓存+分布+集群等问题,大家也必须要了解掌握,不过我都帮大家找到了大厂面试原题,相信你看完这32道Redis面试题解读,会对Redis有更好的理解,应对面试官的提问也更加得心应手。
Redis,英文全称是RemoteDictionaryServer(远程字典服务),是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
与MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁。除此之外,Redis支持事务、持久化、LUA脚本、LRU驱动事件、多种集群方案。
2.说说Redis的基本数据结构类型大多数小伙伴都知道,Redis有以下这五种基本类型:
String(字符串)
Hash(哈希)
List(列表)
Set(集合)
zset(有序集合)
它还有三种特殊的数据结构类型
Geospatial
Hyperloglog
Bitmap
3.Redis为什么这么快?分布式环境下(单机就不用说了)非常容易出现缓存和数据库间的数据一致性问题,针对这一点的话,只能说,如果你的项目对缓存的要求是强一致性的,那么请不要使用缓存。我们只能采取合适的策略来降低缓存和数据库间数据不一致的概率,而无法保证两者间的强一致性。合适的策略包括合适的缓存更新策略,更新数据库后要及时更新缓存、缓存失败时增加重试机制,例如MQ模式的消息队列。
5.布隆过滤器bloomfilter就类似于一个hashset,用于快速判某个元素是否存在于集合中,其典型的应用场景就是快速判断一个key是否存在于某容器,不存在就直接返回。布隆过滤器的关键就在于hash算法和容器大小
6..缓存雪崩问题存在同一时间内大量键过期(失效),接着来的一大波请求瞬间都落在了数据库中导致连接异常。
解决方案:
也是像解决缓存穿透一样加锁排队。
建立备份缓存,缓存A和缓存B,A设置超时时间,B不设值超时时间,先从A读缓存,A没有读B,并且更新A缓存和B缓存;
7.缓存并发问题这里的并发指的是多个redis的client同时setkey引起的并发问题。比较有效的解决方案就是把redis.set操作放在队列中使其串行化,必须的一个一个执行,具体的代码就不上了,当然加锁也是可以的,至于为什么不用redis中的事务,留给各位看官自己思考探究。
8.Redis分布式redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。
这是一个典型的分布式读写分离模型。我们可以利用master来插入数据,slave提供检索服务。这样可以有效减少单个机器的并发访问数量
9.读写分离模型通过增加SlaveDB的数量,读的性能可以线性增长。为了避免MasterDB的单点故障,集群一般都会采用两台MasterDB做双机热备,所以整个集群的读和写的可用性都非常高。读写分离架构的缺陷在于,不管是Master还是Slave,每个节点都必须保存完整的数据,如果在数据量很大的情况下,集群的扩展能力还是受限于单个节点的存储能力,而且对于Write-intensive类型的应用,读写分离架构并不适合。
10.数据分片模型为了解决读写分离模型的缺陷,可以将数据分片模型应用进来。
可以将每个节点看成都是独立的master,然后通过业务实现数据分片。
结合上面两种模型,可以将每个master设计成由一个master和多个slave组成的模型。
11.redis常见性能问题和解决方案:Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
尽量避免在压力很大的主库上增加从库
12.redis通讯协议RESP是redis客户端和服务端之前使用的一种通讯协议;RESP的特点:实现简单、快速解析、可读性好
13.Redis分布式锁实现先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。**如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?**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还包括进程运行本身需要的内存、内存碎片等,但是不包括虚拟内存。
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的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的*。
22.Redis哨兵在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的*。
23.MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
##24.Redis有哪些适合的场景?
(1)、会话缓存(SessionCache)最常用的一种使用Redis的情景是会话缓存(sessioncache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗?幸运的是,随着Redis这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。
(2)、全页缓存(FPC)除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。此外,对WordPress的用户来说,Pantheon有一个非常好的插件wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
(3)、队列Reids在内存存储引擎领域的一大优点是提供list和set操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对list的push/pop操作。如果你快速的在Google中搜索“Redisqueues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。
(4),排行榜/计数器Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(SortedSet)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可:当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:ZRANGEuser_scores010WITHSCORESAgoraGames就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。
(5)、发布/订阅最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!(不,这是真的,你可以去核实)。
26.一个Redis实例最多能存放多少的keys?List、Set、SortedSet他们最多能存放多少元素?理论上Redis可以处理多达232的keys,并且在实际中进行了测试,每个实例至少存放了2亿5千万的keys。我们正在测试一些较大的值。任何list、set、和sortedset都可以放232个元素。换句话说,Redis的存储极限是系统中的可用内存值。
27.Redis常见性能问题和解决方案?(1)Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件(2)如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次(3)为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内(4)尽量避免在压力很大的主库上增加从库(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开始,可以从AOF切换到RDB的快照持久性或其他方式而不需要重启Redis。检索‘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这个范围的槽而不可用。
作者:Java架构师