java分布式⾯试题_2021,Java最全的分布式⾯试题合集附答
案,共2w字!
分布式分为分布式缓存(Redis)、分布式锁(Redis 或 Zookeeper)、分布式服务(Dubbo 或 SpringCloud)、分布式服务协调(Zookeeper)、分布式消息队列(Kafka 、RabbitMq)、分布式 Session 、分布式事务、分布式搜索(Elasticsearch)等。不可能所有分布式内容都熟悉,⼀定要在某个领域有所专长。
⼀、分布式理论
问:分布式有哪些理论?
CAP 、BASE。分布式 CAP 理论,任何⼀个分布式系统都⽆法同时满⾜ Consistency(⼀致性)、Availability(可⽤性)、Partition tolerance(分区容错性) 这三个基本需求。最多只能满⾜其中两项。⽽ Partition tolerance(分区容错性) 是必须的,因此⼀般是 CP ,或者AP。
问:你怎么理解分布式⼀致性?
数据⼀致性通常指关联数据之间的逻辑关系是否正确和完整。在分布式系统中,数据⼀致性往往指的是由于数据的复制,不同数据节点中的数据内容是否完整并且相同。
⼀致性还分为强⼀致性,弱⼀致性,还有最终⼀致性。强⼀致性就是马上就保持⼀致。
最终⼀致性是指经过⼀段时间后,可以保持⼀致。
⼆、分布式事务
问:你怎么理解分布式事务?分布式事务的协议有哪些?
分布式事务是指会涉及到操作多个数据库的事务。⽬的是为了保证分布式系统中的数据⼀致性。分布式事务类型:⼆阶段提交 2PC ,三阶段提交 3PC。
2PC :第⼀阶段:准备阶段(投票阶段)和第⼆阶段:提交阶段(执⾏阶段)。
3PC :三个阶段:CanCommit 、PreCommit 、DoCommit。
问:分布式事务的解决⽅案有哪些?
分布式事务解决⽅案:补偿机制 TCC 、XA 、消息队列 MQ。
问:讲⼀下 TCC。
T(Try)锁资源:锁定某个资源,设置⼀个预备类的状态,冻结部分数据。
⽐如,订单的⽀付状态,先把状态修改为"⽀付中(PAYING)"。
⽐如,本来库存数量是 100 ,现在卖出了 2 个,不要直接扣减这个库存。在⼀个单独的冻结库存的字段,⽐如 prepare _ remove _ stock 字段,设置⼀个 2。也就是说,有 2 个库存是给冻结了。
积分服务的也是同理,别直接给⽤户增加会员积分。你可以先在积分表⾥的⼀个预增加积分字段加⼊积分。
⽐如:⽤户积分原本是 1190 ,现在要增加 10 个积分,别直接 1190 + 10 = 1200 个积分啊!你可以保持积分为 1190 不变,在⼀个预增加字段⾥,⽐如说 prepare _ add _ credit 字段,设置⼀个 10 ,表⽰有 10 个积分准备增加。
C(Confirm):在各个服务⾥引⼊了⼀个 TCC 分布式事务的框架,事务管理器可以感知到各个服务的 Try 操作是否都成功了。假如都成功了, TCC 分布式事务框架会控制进⼊ TCC 下⼀个阶段,第⼀个 C 阶段,也就是 Confirm 阶段。此时,需要把 Try 阶段锁住的资源进⾏处理。
⽐如,把订单的状态设置为“已⽀付(Payed)”。
⽐如,扣除掉相应的库存。
⽐如,增加⽤户积分。
C(Cancel):在 Try 阶段,假如某个服务执⾏出错,⽐如积分服务执⾏出错了,那么服务内的 TCC 事务框架是可以感知到的,然后它会决定对整个 TCC 分布式事务进⾏回滚。
TCC 分布式事务框架只要感知到了任何⼀个服务的 Try 逻辑失败了,就会跟各个服务内的 TCC 分布式事务框架进⾏通信,然后调⽤各个服务的 Cancel 逻辑。也就是说,会执⾏各个服务的第⼆个 C 阶段, Cancel 阶段。
⽐如,订单的⽀付状态,先把状态修改为" closed "状态。
⽐如,冻结库存的字段, prepare _ remove _ stock 字段,将冻结的库存 2 清零。
⽐如,预增加积分的字段, prepare _ add _ credit 字段,将准备增加的积分 10 清零。
问:事务管理器宕掉了,怎么办?
做冗余,设置多个事务管理器,⼀个宕掉了,其他的还可以⽤。
问:怎么保证分布式系统的幂等性?
状态机制。版本号机制。
三、Redis
问:Redis 有哪些优势?
速度快,因为数据存在内存中。
⽀持丰富数据类型,⽀持 string、list、set 、sorted set、hash。
⽀持事务,操作都是原⼦性,所谓的原⼦性就是对数据的更改要么全部执⾏,要么全部不执⾏。
丰富的特性:可⽤于缓存,消息,按 key 设置过期时间,过期后将会⾃动删除。
单线程,单进程,采⽤ IO 多路复⽤技术。
问:Redis 的存储结构是怎样的?
key-value 键值对。
问:Redis ⽀持哪些数据结构?
string(字符串), hash(哈希), list(队列), set(集合)及 zset(sorted set 有序集合)。
问:Redis 的数据结构,有哪些应⽤场景?
string:简单地 get / set 缓存。
hash:可以缓存⽤户资料。⽐如命令:hmset user1 name "lin" sex "male" age "25" ,缓存⽤户 user1 的资料,姓名为 lin ,性别为男,年龄 25。
list:可以做队列。往 list 队列⾥⾯ push 数据,然后再 pop 出来。
zset:可以⽤来做排⾏榜。
问:Redis 的数据结构,底层分别是由什么实现的?java面试八股文
Redis 字符串,却不是 C 语⾔中的字符串(即以空字符 ’\0’ 结尾的字符数组),它是⾃⼰构建了⼀种名为 简单动态字符串(simple dynamic string , SDS)的抽象类型,并将 SDS 作为 Redis 的默认字符串表⽰。
Redi List ,底层是 ZipList ,不满⾜ ZipList 就使⽤双向链表。ZipList 是为了节约内存⽽开发的。和各种语⾔的数组类似,它是由连续的内存块组成的,这样⼀来,由于内存是连续的,就减少了很多内存碎⽚和指针的内存占⽤,进⽽节约了内存。
问:Redis 怎么保证可靠性?Redis 的持久化⽅式有哪些?有哪些优缺点?
⼀个可靠安全的系统,肯定要考虑数据的可靠性,尤其对于内存为主的 Redis ,就要考虑⼀旦服务器挂掉,启动之后,如何恢复数据的问题,也就是说数据如何持久化的问题。
AOF 就是备份操作记录。AOF 由于是备份操作命令,备份快、恢复慢。
AOF 的优点:AOF 更好保证数据不会被丢失,最多只丢失⼀秒内的数据。另外重写操作保证了数据的有效性,即使⽇志⽂件过⼤也会进⾏重写。AOF 的⽇志⽂件的记录可读性⾮常的⾼。
AOF 的缺点:对于相同数量的数据集⽽⾔, AOF ⽂件通常要⼤于 RDB ⽂件。
RDB 就是备份所有数据,使⽤了快照。RDB 恢复数据⽐较快。
问:AOF ⽂件过⼤,怎么处理?
会进⾏ AOF ⽂件重写。
随着 AOF ⽂件越来越⼤,⾥⾯会有⼤部分是重复命令或者可以合并的命令。
重写的好处:减少 AOF ⽇志尺⼨,减少内存占⽤,加快数据库恢复时间。
执⾏⼀个 AOF ⽂件重写操作,重写会创建⼀个当前 AOF ⽂件的体积优化版本。
问:讲⼀下 Redis 的事务。
先以 MULTI 开始⼀个事务, 然后将多个命令⼊队到事务中, 最后由 EXEC 命令触发事务, ⼀并执⾏事务中的所有命令。如果想放弃这个事务,可以使⽤ DISCARD 命令。
问:Redis 事务⽆法回滚,那怎么处理?
问:怎么设置 Redis 的 key 过期时间?
key 的的过期时间通过 EXPIRE key seconds 命令来设置数据的过期时间。返回 1 表明设置成功,返回 0 表明 key 不存在或者不能成功设置过期时间。
问:Redis 的过期策略有哪些?
惰性删除:当读/写⼀个已经过期的 key 时,会触发惰性删除策略,直接删除掉这个过期 key ,并按照 key 不存在去处理。惰性删除,对内存不太好,已经过期的 key 会占⽤太多的内存。
定期删除:每隔⼀段时间,就会对 Redis 进⾏检查,主动删除⼀批已过期的 key。
问:为什么 Redis 不使⽤定时删除?
定时删除,就是在设置 key 的过期时间的同时,创建⼀个定时器,让定时器在过期时间来临时,⽴即执⾏对 key 的删除操作。
定时删会占⽤ CPU ,影响服务器的响应时间和性能。
问:Redis 的内存回收机制都有哪些?
当前已⽤内存超过 maxmemory 限定时,会触发主动清理策略,也就是 Redis 的内存回收策略。
LRU 、TTL。
noeviction :默认策略,不会删除任何数据,拒绝所有写⼊操作并返回客户端错误信息,此时 Redis 只响应读操作。
volatitle - lru :根据 LRU 算法删除设置了超时属性的键,知道腾出⾜够空间为⽌。如果没有可删除的键对象,回退到 noeviction 策略。
allkeys - lru :根据 LRU 算法删除键,不管数据有没有设置超时属性,直到腾出⾜够空间为⽌。
allkeys - random :随机删除所有键,知道腾出⾜够空间为⽌。
volatitle - random :随机删除过期键,知道腾出⾜够空间为⽌。
volatitle - ttl :根据键值对象的 ttl 属性,删除最近将要过期数据。如果没有,回退到 noeviction 策略。
问:⼿写⼀下 LRU 算法。
问:Redis 的搭建有哪些模式?
主从模式、哨兵模式、Cluster(集)模式。最好是⽤集模式。
问:你⽤过的 Redis 是多主多从的,还是⼀主多从的?集⽤到了多少节点?⽤到了多少个哨兵?
集模式。三主三从。
问:Redis 采⽤多主多从的集模式,各个主节点的数据是否⼀致?
问:Redis 集有哪些特性
master 和 slaver。主从复制。读写分离。哨兵模式。
问:Redis 是怎么进⾏⽔平扩容的?
问:Redis 集数据分⽚的原理是什么?
Redis 数据分⽚原理是哈希槽(hash slot)。
Redis 集有 16384 个哈希槽。每⼀个 Redis 集中的节点都承担⼀个哈希槽的⼦集。
哈希槽让在集中添加和移除节点⾮常容易。例如,如果我想添加⼀个新节点 D ,我需要从节点 A 、B、C 移动⼀些哈希槽到节点 D。同样地,如果我想从集中移除节点 A ,我只需要移动 A 的哈希槽到 B 和 C。当节点 A 变成空的以后,我就可以从集中彻底删除它。因为从⼀个节点向另⼀个节点移动哈希槽并不需要停⽌操作,所以添加和移除节点,或者改变节点持有的哈希槽百分⽐,都不需要任何停机时间(downtime)。
问:讲⼀下⼀致性 Hash 算法。
⼀致性 Hash 算法将整个哈希值空间组织成⼀个虚拟的圆环, 我们对 key 进⾏哈希计算,使⽤哈希后的结果对 2 ^ 32 取模,hash 环上必定有⼀个点与这个整数对应。依此确定此数据在环上的位置,从此位置沿环顺时针“⾏⾛”,第⼀台遇到的服务器就是其应该定位到的服务器。
⼀致性 Hash 算法对于节点的增减都只需重定位环空间中的⼀⼩部分数据,具有较好的容错性和可扩展性。
⽐如,集有四个节点 Node A 、B 、C 、D ,增加⼀台节点 Node X。Node X 的位置在 Node B 到 Node C 直接,那么受到影响的仅仅是 Node B 到 Node X 间的数据,它们要重新落到 Node X 上。
所以⼀致性哈希算法对于容错性和扩展性有⾮常好的⽀持。
问:为什么 Redis Cluster 分⽚不使⽤ Redis ⼀致性 Hash 算法?
⼀致性哈希算法也有⼀个严重的问题,就是数据倾斜。
如果在分⽚的集中,节点太少,并且分布不均,⼀致性哈希算法就会出现部分节点数据太多,部分节点数据太少。也就是说⽆法控制节点存储数据的分配。
问:集的拓扑结构有没有了解过?集是怎么连接的?
⽆中⼼结构。Redis-Cluster 采⽤⽆中⼼结构,每个节点保存数据和整个集状态,每个节点都和其他所有节点连接。
问:讲⼀下 Redis 主从复制的过程。
从机发送 SYNC(同步)命令,主机接收后会执⾏ BGSAVE(异步保存)命令备份数据。
主机备份后,就会向从机发送备份⽂件。主机之后还会发送缓冲区内的写命令给从机。
当缓冲区命令发送完成后,主机执⾏⼀条写命令,就会往从机发送同步写⼊命令。
问:讲⼀下 Redis 哨兵机制。
下⾯是 Redis 官⽅⽂档对于哨兵功能的描述:
监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。
⾃动故障转移(Automatic Failover):当主节点不能正常⼯作时,哨兵会开始⾃动故障转移操作,它会将失效主节点的其中⼀个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
配置提供者(Configuration Provider):客户端在初始化时,通过连接哨兵来获得当前 Redis 服务的主节点地址。
通知(Notification):哨兵可以将故障转移的结果发送给客户端。
问:讲⼀下布隆过滤器。
布隆过滤器的主要是由⼀个很长的⼆进制向量和若⼲个(k 个)散列映射函数组成。因为每个元数据的存储信息值固定,⽽且总的⼆进制向量固定。所以在内存占⽤和查询时间上都远远超过⼀般的算法。当然存在⼀定的不准确率(可以控制)和不容易删除样本数据。
布隆过滤器的优点:⼤批量数据去重,特别的占⽤内存。但是⽤布隆过滤器(Bloom Filter)会⾮常的省内存。
布隆过滤器的特点:当布隆过滤器说某个值存在时,那可能就不存在,如果说某个值不存在时,那肯定就是不存在了。
布隆过滤器的应⽤场景:新闻推送(不重复推送)。解决缓存穿透的问题。
四、缓存
问:缓存雪崩是什么?
如果缓存数据设置的过期时间是相同的,并且 Redis 恰好将这部分数据全部删光了。这就会导致在这段时间内,这些缓存同时失效,全部请求到数据库中。这就是缓存雪崩。
问:怎么解决缓存雪崩?
解决⽅法:在缓存的时候给过期时间加上⼀个随机值,这样就会⼤幅度的减少缓存在同⼀时间过期。
问:缓存穿透是什么?
缓存穿透是指查询⼀个⼀定不存在的数据。由于缓存不命中,并且出于容错考虑,如果从数据库查不到数据则不写⼊缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。
问:怎么解决缓存穿透?
问:什么是缓存与数据库双写⼀致问题?
问:如何保证缓存与数据库的⼀致性?
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放⼊缓存,同时返回响应。
先删除缓存,再更新数据库。
问:为什么是先删除缓存,⽽不是先更新缓存?
问:先更新数据库,再删除缓存,会有什么问题?
先更新数据库,再删除缓存。可能出现以下情况:
如果更新完数据库, Java 服务提交了事务,然后挂掉了,那 Redis 还是会执⾏,这样也会不⼀致。
如果更新数据库成功,删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据就出现了不⼀致。
先删除缓存,再更新数据库。
如果删除缓存失败,那就不更新数据库,缓存和数据库的数据都是旧数据,数据是⼀致的。
如果删除缓存成功,⽽数据库更新失败了,那么数据库中是旧数据,缓存中是空的,数据不会不⼀致。因为读的时候缓存没有,所以去读了数据库中的旧数据,然后更新到缓存中。
问:先删除缓存,在写数据库成功之前,如果有读请求发⽣,可能导致旧数据⼊缓存,引发数据不⼀致,怎么处理?
分布式锁
问:Redis 如何实现分布式锁?
使⽤ set key value ex nx 命令。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论