<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>面试题 &#8211; 有意与无意之间</title>
	<atom:link href="https://zhangxihai.cn/archives/tag/%E9%9D%A2%E8%AF%95%E9%A2%98/feed" rel="self" type="application/rss+xml" />
	<link>https://zhangxihai.cn</link>
	<description>千淘万漉虽辛苦 吹尽狂沙始到金 - 生命不息 编程不止</description>
	<lastBuildDate>Fri, 05 Mar 2021 08:42:53 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.11</generator>
	<item>
		<title>RabbitMQ面试题汇总</title>
		<link>https://zhangxihai.cn/archives/152</link>
					<comments>https://zhangxihai.cn/archives/152#respond</comments>
		
		<dc:creator><![CDATA[胖爷]]></dc:creator>
		<pubDate>Fri, 22 Feb 2019 05:46:29 +0000</pubDate>
				<category><![CDATA[其它]]></category>
		<category><![CDATA[MQ]]></category>
		<category><![CDATA[Rabbitmq]]></category>
		<category><![CDATA[面试题]]></category>
		<guid isPermaLink="false">https://zhangxihai.cn/?p=152</guid>

					<description><![CDATA[1 为什么要使用MQ？MQ和Redis模拟消息队列相比有什么优点？ 为什么要使用MQ 解耦，系统与系统之间的耦合。 异步，非必要的业务逻辑可以以异步方式运行，加快响应速度 消峰，减少并发 对比Redis消息队列 消息消费的可靠性 Redis没有相应的机制保证消息的消费，当消费者消费失败的时候，消息体丢失，需要手动处理, 例如用数据库、File等进行存储，以保...]]></description>
										<content:encoded><![CDATA[<h4>1 为什么要使用MQ？MQ和Redis模拟消息队列相比有什么优点？</h4>
<p><strong>为什么要使用MQ</strong></p>
<ol>
<li>解耦，系统与系统之间的耦合。</li>
<li>异步，非必要的业务逻辑可以以异步方式运行，加快响应速度</li>
<li>消峰，减少并发</li>
</ol>
<p><strong>对比Redis消息队列</strong></p>
<ol>
<li>消息消费的可靠性<br />
Redis没有相应的机制保证消息的消费，当消费者消费失败的时候，消息体丢失，需要手动处理, 例如用数据库、File等进行存储，以保证队列可以重新处理；</li>
</ol>
<p>MQ一般都有消费确认机制，即使消费失败，也会自动使得消息体返回原队列，同时可全程持久化，保证消息体被正确消费；</p>
<ol start="2">
<li>
<p>发布的可靠性<br />
Redis不提供发布确认，需要自行实现，而MQ通常都有发布确认功能，保证消息被发布到服务器；</p>
</li>
<li>
<p>高可用<br />
Redis故障转移方案不够完美，而MQ集群通常采用磁盘、内存节点，任意单带那故障都不会影响整个队列的操作；</p>
</li>
<li>
<p>持久化<br />
Redis是数据持久化到磁盘，并不是单独针对消息队列。MQ通常队列、消息都可以单独选择是否持久化到磁盘。</p>
</li>
<li>
<p>消费者负载均衡<br />
Redis不提供，需要自行实现，MQ通常根据消费者情况，进行消息的均衡分发；</p>
</li>
<li>
<p>队列监控<br />
Redis不提供，需要自行实现，,Q可以兼容某个队列的所有信息（内存、磁盘、消费者、生产者、速率等）。</p>
</li>
<li>
<p>流量控制<br />
不提供，需要自行实现，MQ通常早服务器过载的情况下，对生产者速率进行限制，保证服务可靠性</p>
</li>
<li>
<p>出入对性能<br />
高并发下，MQ的入队性能通常高于Redis。</p>
</li>
</ol>
<h4>2 RabbitMQ中Broker指什么，cluster又是指什么？</h4>
<p>broker是指一个或多个erlong node的逻辑分组，且node导航运行着rabbitma的应用程序。</p>
<p>cluster是再broker基础之上，增加node之间共享元数据的约束；</p>
<h4>3 RabbitMQ的消息基于什么传输?</h4>
<p>由于TCP连接的创建和小会开销较大，且并发数受系统资源限制，会造成性能瓶颈，RabbitMQ使用信道的方式来传输数据。信道是建立在真实的TCP内的虚拟连接，且每条TCP连接上的信道数量没有限制；</p>
<h4>4 RabbitMQ的消息时如何分发的？</h4>
<p>如果队列至少有一个消费者订阅，消息将以循环的方式发送给消费者。每条消息只会分发给一个订阅的消费者（前提是消费者能够正常处理消息并进行确认）；</p>
<h4>5 消息怎么路由？</h4>
<p>消息理由有三部分：交换器、路由、绑定。生产者把消息发布到交换器上，绑定决定了消息如何从路由器器路由到特定的队列；消息最终到达队列，并被消费者接收；</p>
<p>消息发布到交换器时，消息将用于一个路由键，在消息创建时设定。</p>
<p>通过队列路由键，可以把队列绑定到交换器上。</p>
<p>消息到达交换器后，RabbitMQ会将消息的路由键与队列的路由键进行匹配，如果能够匹配到队列，则消息会投递到相应的队列中； 如果不能匹配到任何队列，消息将进入黑洞。</p>
<p>常用交换器有三种：</p>
<ul>
<li><strong>direct</strong>：如果路由键完全匹配，消息就诶投递到相应的队列；</li>
<li><strong>fanout</strong>: 如果交换器收到消息，将会广播到所有绑定的队列上；</li>
<li><strong>topic</strong> 可以使来自不同源头的消息能够匹配到达同一个队列。</li>
</ul>
<h4>6 如何确保消息正确地发送至RabbitMQ</h4>
<p>Rabiitmq使用发送确认模式，确保消息正确地发送到RabbitMQ.<br />
发送确认模式：将信道设置成confirm模式（发送方确认模式），则所有在信道上发布的消息都会被指派一个唯一ID。一旦消息被投递到目的队列后，或者消息被写入磁盘后，信道会发送一个确认给生产者（包含消息唯一ID）。如果RabbitMQ内部错误从而导致消息丢失，会发送一跳未确认消息。发送方确认模式是异步的，生产者应用程序在等待确认的同事，可以继续发送消息。当确认消息到达生产者应用程序，生产者应用程序的回调方法就会被处罚来处理确认消息。</p>
<h4>7 如何保证消息接收方消费了消息？</h4>
<p>消费者接受每一条消息后都必须进行确认（消息接收和消息确认是两个不同操作）。只有消费者确认了消息，RabbitMQ才能安全第把消息从队列中删除。这里并没用用到超时机制，RabbitMQ仅通过Consumer的链接中断来确认会否需要重新发送消息。也就是说，只要链接不中断，Rabbitmq给了Consumer足够长的时间来处理消息。</p>
<p>特殊情况：</p>
<ul>
<li>如果消费者接收到消息，在确认之前断开了连接或取消订阅，RabbitMQ会认为消息没有被分发，然后重新分发给下一个订阅的消费者；</li>
<li>吐过消费者接收到消息却没有确认消息，连接也未断开，则RabbitMQ认为该消费者繁忙，将不会给消费者分发更多的消息;</li>
</ul>
<h4>8 如何避免消息重复投递或重复消费？</h4>
<p>在消息生产时，MQ内部针对每条生产者发送的消息生成一个inner-msg-id，做为去重和幂等的依据，避免重复的消息进入队列。在消息消费时，要求消息体重必须要有一个bizId做为去重和幂等的依据，避免同一消息被重复消费。</p>
<h4>9 如何解决丢数据的问题？</h4>
<p><strong>生产者丢数据</strong><br />
开启transaction和confirm模式来保证生产者不丢消息。</p>
<p>transaction类似于数据库事务，发送过程中发送异常事务就会回滚。</p>
<p>confirm是确认机制，投递成功则发一条ACK给生产者，投递失败则发一条NACK给生产者，以便重试。</p>
<p>如果是rabbitmq断连，程序员异常，则需要进行异常处理，进行本地端记录，但由于无法保证全部异常都处理， 也可以将投递的消息全部存于本地后，投递成功则标记。</p>
<p><strong>消息队列丢数据</strong><br />
开启持久化磁盘配置，配合comfirm机制，rabbitmq在持久话后，才会给生产者发送ACK。</p>
<p><strong>消费者丢数据</strong><br />
启用手动确认模式</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zhangxihai.cn/archives/152/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Redis面试题汇总</title>
		<link>https://zhangxihai.cn/archives/151</link>
					<comments>https://zhangxihai.cn/archives/151#respond</comments>
		
		<dc:creator><![CDATA[胖爷]]></dc:creator>
		<pubDate>Wed, 22 Feb 2017 05:44:07 +0000</pubDate>
				<category><![CDATA[其它]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[面试题]]></category>
		<guid isPermaLink="false">https://zhangxihai.cn/?p=151</guid>

					<description><![CDATA[1 请说出你对Redis的认识，Redis有哪些优缺点？ Redis是一个使用C语言编写，开源的高性能非关系型数据库。 Redis有5种数据存储类型，健的类型只能是字符串，值的类型可以是：字符串、列表、集合、散列表、有序集合。 Redis的数据存储在内存之中，所以读写速度非常快，每秒可以处理超过10万次数据读写操作。 优点 读写性能优异，读速度可达11000...]]></description>
										<content:encoded><![CDATA[<h4>1 请说出你对Redis的认识，Redis有哪些优缺点？</h4>
<p>Redis是一个使用C语言编写，开源的高性能非关系型数据库。</p>
<p>Redis有5种数据存储类型，健的类型只能是字符串，值的类型可以是：字符串、列表、集合、散列表、有序集合。</p>
<p>Redis的数据存储在内存之中，所以读写速度非常快，每秒可以处理超过10万次数据读写操作。</p>
<p><strong>优点</strong></p>
<ul>
<li>读写性能优异，读速度可达110000次/秒，写速度可达到81000次/秒；</li>
<li>支持数据持久化，支持AOF和RDB两种数据持久化；</li>
<li>支持事务，Redis所有操作都是原子性的，同时Redis还支持对几个操作合并后的原子性操作；</li>
<li>数据结构丰富，除了支持string外，还支持hash、set、zset、list等数据结构；</li>
<li>支持主从复制，主机会自动将数据同步到从机，可以进行读写分离；</li>
</ul>
<p><strong>缺点</strong></p>
<ul>
<li>易受物理内存限制，不能作为海量数据的高性能读写，因此适应场景主要局限在较小数据量的高性能操作和运算上；</li>
<li>不具备容错和恢复功能，主机从机的宕机都会导致前端部分读写请求失败，需要等待机器重启或手动切换前端IP才能恢复；</li>
<li>主机宕机，宕机前有部分数据未能及时同步到从机，切换IP后还会引发数据不一致问题，降低可用性；</li>
<li>Redis较难支持在线扩容，在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题，运维人员在系统上线时必须确保有足够的空间，这会对资源造成很大的浪费；</li>
</ul>
<h4>2 Redis为什么会这么快？</h4>
<ol>
<li>完全基于内存，绝大部分请求也是纯粹的内存操作，所以非常快速。数据在内存中，类似于HashMap，时间复杂度是O(1)</li>
<li>数据结构简单，所以数据操作也简单，这些数据结构是专门设计的。</li>
<li>采用单线程，这就避免了不必要的上下文切换和竞争条件，也不存在多进程或多线程导致的切换而消耗CPU，不用去考虑各种锁的问题，不存在加锁释放锁操作，没有因为可能出现死锁而出现的性能损耗；</li>
<li>使用多路I/O复用模型，非阻塞型IO；</li>
<li>使用底层模型不同，他们之间底层实现方式以及客户端之间通讯的应用协议不一样，Redis直接构建了自己的VM机制，因为一般的系统调用系统函数的话，会浪费一定的时间去移动和请求；</li>
</ol>
<h4>3 Redis有哪些数据类型，分别应用在什么场景?</h4>
<p><strong>string</strong><br />
可以存储字符串、整数、浮点数，适用于简单的健值对存储。<br />
应用场景：</p>
<ul>
<li>分布式锁</li>
<li>计数</li>
<li>序列化对象</li>
</ul>
<p><strong>hash</strong><br />
键值对集合，适用于存储结构化数据，例如对象。</p>
<p><strong>list</strong><br />
列表，可以从两端插入和弹出，按照插入顺序排序。适用于存储消息队列，有序数据。</p>
<p><strong>set</strong><br />
string无序集合，通过hash表实现。可执行交、并、差的操作，适用于例如粉丝列表等。</p>
<p><strong>zset</strong><br />
有序集合。可去重，可排序。</p>
<h4>4 Redis有哪些持久化方式？优缺点分别是什么？</h4>
<p>持久化是将内存数据写到磁盘中去，防止宕机数据丢失。</p>
<p>Rds提供了两种持久化方式，RDB和AOF</p>
<p><strong>RDB</strong><br />
快早持久化，默认持久化方式。Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本，Redis创建快照后，可以对快照进行备份，可以将快照复制到其它服务器从而创建具有相同数据的服务器副本，还可以将快照留在原地以便重启服务器的时候使用。</p>
<p>redis.conf配置</p>
<pre><code>save 900 10</code></pre>
<p>在300秒之后，如果至少有10个KEY发生变化，REDIS就会自动触发BGSAVE命令创建快照。</p>
<p><strong>AOF</strong><br />
AOF持久化实时性更好，是目前主流的持久化方案，开启AOF命令：</p>
<pre><code>appendonly yes</code></pre>
<p>开启AOF持久化后每执行一条会更改Redis中的数据的命令，Redis就会将该命令写入磁盘的AOF文件。AOF文件的保存位置和RDB文件的位置相同，都是通过DIR参数设置的，默认的文件名appendonly.aof</p>
<p>AOF可以配置三种不同的持久化方式</p>
<ol>
<li>
<p>appednfsync always<br />
每次有数据修改发生时都会写入AOF文件，这种方式会严重降低Redis的速度</p>
</li>
<li>
<p>appendfsync everysec<br />
每秒钟同步一次，显式地将多个写命令同步到硬盘</p>
</li>
<li>
<p>appendfsync no<br />
让操作系统决定何时进行同步</p>
</li>
</ol>
<p>为了兼顾数据和写入性能，用户可以考虑appendfsync everysec玄子昂，让redis美妙同步一次AOF文件，Redis性能几乎没有收到任何影响。而且这样即使出现系统奔溃，用户最多只会丢失疫苗之内产生的数据。当硬盘忙于执行写入操作的时候，Redis还会优雅的放慢自己的速度以便适应硬盘的的最大写入速度。</p>
<p><strong>混合持久化</strong><br />
Redis4.0开始支持，AOF重写的时候就直接把RDB的内容写到AOF文件开头。这样做综合了RDB和AOF的有点，快速加载同时避免丢失过多的数据。缺点是，AOF里面的RDB部分是压缩格式不再是AOF格式，可读性差。</p>
<h4>5 什么是缓存雪崩和缓存穿透，如何解决？</h4>
<p><strong>缓存雪崩</strong></p>
<p>缓存同意时间大面积失效，后续请求落到数据库上，造成数据库短时间内承受大量请求而崩掉。</p>
<p>解决办法：</p>
<ul>
<li>保证redis集群的高可用性，发现有机器宕机就尽快补上，选择合适的内存淘汰策略；</li>
<li>系统上线前，对缓存进行预热；</li>
<li>让缓存的过期时间合理均匀分布；</li>
<li>加排斥锁；</li>
<li>缓存过期标记+异步刷新</li>
</ul>
<p><strong>缓存穿透</strong><br />
黑客故意请求缓存中不存在的数据，导致所有请求都落到数据库上，造成数据库短时间内承受大量请求而崩掉。</p>
<p>解决办法：</p>
<ul>
<li>最简单的办法就是将空结果进行缓存，但是不要太长时间；</li>
<li>复杂一点的办法就是使用布隆过滤器，将所有可能存在的数据哈希到一个足够大的bitmap中，不存在的数据肯定会被bitmap兰及诶啊哦。</li>
</ul>
<h4>6 如何解决Redis并发竞争Key问题？</h4>
<p>多个系统同时对一个KEY进行操作，但是最后执行的顺序和我们期望的殊勋不同，这样就导致了结果的不同。</p>
<p>解决办法：<br />
使用分布式锁。<br />
基于zookeeper临时有序节点可以实现分布式锁，大致思想为:每个客户端对某个方法加锁时，在zookeeper上的域该方法对应的指定节点的目录下，生成一个唯一的瞬时有序节点。判断是否货物所的方式很简单，值需要判断有序节点中序号最小的一个。当锁释放的时候，只需要将这个瞬时节点删除即可。同时，其可以表面服务宕机导致的锁无法释放，而产生的死锁问题。完成业务流程后，删除对应的子节点释放锁。</p>
<h4>7 Redis如何实现分布式锁？</h4>
<ol>
<li>
<p>加锁<br />
NX操作，写入随机值，设置鬼泣时间，避免死锁。</p>
</li>
<li>
<p>解锁<br />
解锁必须确保操作的原子性，所以需要借助LUA先判断随机值是否相等再解锁</p>
</li>
</ol>
<h4>8 详述Redis过期策略和内存淘汰机制？</h4>
<p><strong>定时删除</strong></p>
<ol>
<li>设置键的过期时间时，创建一个Timer, 当过期时间到临时，立刻删除键；</li>
<li>内存友好型策略，一旦键过期，就会被删除，并释放所占用的内存，CPU不友好，当一批数量比较多的键过期时，正好遇上CPU紧张的时段，这时候需要的事CPU处理能力，而不是内存。显然CPU时间用在删除过期键上，会对服务器的响应时间和吞吐量造成影响。另外当前Redis时间事件无法搞笑处理大量时间事件，所以定时删除并不是一种号的定时删除策略。</li>
</ol>
<p>Redis默认每个100ms检查，随机抽取KEY进行检查，如果过期则删除，这种操作十分消耗CPU资源。</p>
<p><strong>惰性删除</strong><br />
不管过期的键，在这种策略下，当键在空间中被取出时，首先检查取出的键是否过期，若过期删除该键，否则，返回该键；</p>
<p><strong>定期删除</strong><br />
即内存淘汰策略：</p>
<ul>
<li>noeviction ： 当内存不足以容纳新写入数据时，新写入操作会报错；</li>
<li>allkeys-lru ：当内存不足以容纳新写入数据时，在键空间红，移除最近最少使用的KEY；</li>
<li>allkeys-random : 当内存布椅子容纳新写入数据时，在键空间中，随机移除某个KEY；</li>
<li>volatile-lru ： 当内存不足以容纳写入数据时，在这是了过期时间的键空间中，移除最近最少使用的KEY。 这种情况一般是把Redis即当缓存，又做持久化存储的时候采用。</li>
<li>volatile-random： 当内存不足以容纳新写入数据时，在设置了过期时间的键空间中，有更早过期时间的KEY优先移除。</li>
</ul>
<h4>9 如何保证缓存与数据库双写时的数据一致性？</h4>
<p>数据库和缓存双鞋，就必然会存在不一致的问题。有强一致性的场景，就不能做缓存。</p>
<p>做缓存则代表取最终一致性：</p>
<ol>
<li>采取正确的更新策略，先更新数据库，再删除缓存</li>
<li>如果存在删除缓存失败，提供补偿措施，例如利用消息队列</li>
</ol>
<h4>10 Redis适合那些场景？</h4>
<ol>
<li>Sesion共享（单点登录）</li>
<li>页面缓存</li>
<li>消息队列</li>
<li>分布式锁</li>
<li>排行榜/计数器</li>
<li>发布订阅</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://zhangxihai.cn/archives/151/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
