毕业季-Java分布式开发面试题

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 毕业季-Java分布式开发面试题

缓存击穿,穿透,雪崩


  1. 缓存的目标是提高程序的运行效率。mysql并发量过大,我们可以把数据放入到redis里面来分摊mysql的压力。
  2. 缓存击穿是指缓存的热点数据到期了,同时并发查询该数据的线程都涌向数据库,导致数据库压力瞬间倍增。这个就是缓存击穿。缓存击穿的应对手段:1.缓存永不过期。2.使用锁(本地锁,分布式锁)。
  3. 缓存穿透是指数据库被恶意攻击,客户端每次查询的都是mysql中不存在的数据。解决办法:1.在redis里面把不存在的数据也缓存起来。2.使用布隆过滤器。
  4. 缓存雪崩指的是redis里面缓存的数据同时到期,导致查询数据都来到mysql这。这就是缓存雪崩。解决手段:设置有效时长时可以使用随机数。

为什么要使用Redis,Redis基本数据类型,Redis的持久化机制。


redis是一个内存型的存储了key-value格式的非关系型数据库。他的运行速度比mysql要快很多。redis常见的数据类型:string,list,set,zset,hash。

  1. 字符串应用最广,缓存数据可以使用字符串,我们将java的对象转换为json串存储到redis里面。incr和decr可以实现数字的自增和自减,从而实现粉丝数。
  2. list里面可以获取第一个元素,可以往最后一个元素后放数据,所以他可以实现队列的效果。
  3. set里面可以求交集和并集所以我们可以用set实现共同好友和推荐好友。
  4. zset在保存数据的是有一个分值,所以我们可以用zset实现排行榜功能。
  5. hash他可以应用在存储对象,用它来存储对象比string更好的地方是可以对某个属性进行独立的操作。 redis的持久化是指:redis的数据都在内存中存储,内存的数据都是临时的数据,当硬件断电后数据都会被销毁掉。redis如何实现断电后数据的恢复就是redis的持久化机制。redis有两种持久化手段。第一种叫快照持久化,快照持久化生产的文件后缀是rdb,所以又被称为rdb持久化。第二种持久化叫日志持久化,生产的文件后缀为aof,所以又被称为aof持久化。

cap定理和base定理是什么?


cap是指一个项目的三个特性:p表示分区容错性,a表示的是可用性,c表示的是一致性。


分区容错性指定的是一个项目他被拆分到多个服务上面,就是一个分布式环境,需要各个服务器之间进行通信。我们现在做的项目都需要满足分区容错性。只要你的系统不是一个单机环境,你都要满足分区容错性。


可用性:可用性指的是系统的是否可用正常运行。不会因为一些原因导致系统不做响应。互联网项目的特点是用户至上,所以要满足用户的可用性。银行项目因为涉及到金钱的问题,有些情况会放弃掉可用性。


一致性:系统中的数据不能出错。比如,用户下了一个订单,库存里面的商品就要减一。比如商城类项目用户买完商品后,他的积分要增加。


cap理论研究发现:一个系统的三个特性永远不会同时都满足,我们在开发项目的时候只能选择性的丢弃掉一个特性。ca系统,ap系统,cp系统。ca系统比较少见,军事上一些系统可能会做成ca系统,先保证可用性和一致性。ap系统,互联网性的项目都是ap系统,cp系统经常应用在银行系统中。


base理论就是基于cap理论进行了进一步的阐述:


ba:基本可用,s:软状态。e:最终一致性。


在目前开发环境,分区容错性一定是需要满足的。我们就需要从一致性和可用性进行取舍。base理论要求我们要先满足可用性,使我们的系统达到基本可用。一致性可用适当的放弃。但是一致性不能完全放弃,需要有一个软状态,软状态就是系统数据的不一致状态。这个软状态可用根据情况有一定时限,到达时限后,需要数据一致。这就是最终一致性。

分布式事务的解决方案


分布式事务是要解决在分布式环境中两个服务做不同的操作,能够相互影响,从而保持数据的一致性,不能一个项目事务成功,一个项目事务失败造成数据不一致。

常见的分布式事务有下面三种方式:

  1. 2pc:2阶段提交。是指把事务提交分两个阶段,统一有事务管理器TM来控制。这种是强一致性类型的。
  2. TCC事务补偿。基于base定理实现了最终一致。先提交各个服务的事务。一旦有一个出现异常,然后就采取事务补偿手段对事务进行回滚。
  3. 依据可靠性消息完成分布式事务。

rabbitmq中有可靠性消息投递。可以保证生产者生成的消息一定能被消费者消费。

rabbitmq里面有个ack应答机制。生产者生产完消息后,mq会对接收到的消息进行应答。生产者对哪些没有应答的消息进行重试操作。

消费者,消费完消息后也给mq做ack应答。消息队列才把这个消息删除。

MQ里面做持久化操作防止消息的丢失。

如何保证接口的幂等性。


接口幂等性:我们的控制器接口对外公布服务,外界客户端在请求我们接口,不管请求几次,得到结果跟请求一次是一样的效果,这就是保证了接口幂等性。如果请求了多次,结果产生了问题就违反了接口幂等性。

前端处理,用户点击按钮后,让按钮不能重复点击。

可以使用token处理接口幂等性。我们在前端发请求之前会得到一个token(有服务器端生成的一个唯一标记交给客户端保存),前端发请求的时候可以带着token,我们在redis里面判断这个token是否存在,如果存在就不是第一次请求,如果不存在就是第一次请求。setNx()不存在的时候放入,存在了就不放入。

不是所有的方法都需要判断接口幂等性的,查询和删除都是天然满足接口幂等性的方法。不满足接口幂等性的方法,我们也会选择性的进行接口幂等性的判断。

如何使用redis实现分布式锁。


  1. 防止死锁问题,给锁增加一个有效时长。可以防止死锁。
  2. 如何保证往redis里面放数据,跟设置这个数据的有效时长是一个原子操作,一块执行成功或者一块执行失败。我们可以使用java操作lua脚本实现多个redis命令是一个原子操作。
  3. 当服务运行时长超过了我们设定的锁的有效时长,这时候会产生锁失效。怎么避免这个问题。这时候我们可以在往redis里面加锁的时候,不用指定key为固定的值,可以给每个锁加一个唯一标记,比如uuid,这样每次删锁的时候我们就可以判断,redis里面的锁是不是我们自己的锁。

如何保证缓存的一致性。


mysql的数据和redis缓存中的数据,在多线程操作的时候有可能数据不一致。根据cap定理和base理论,我们可以采用延时双删模式解决这个问题。延时双删,就是指线程在修改mysql数据的时候同时删除一下redis,延迟0.1秒再删除一下redis。这样可以解决掉99%的不一致问题。剩下的1%交给redis里面的定时器。因为我们放入到redis的数据都会给一个有效时长。

哨兵机制的基本流程


哨兵机制就是Redis下的一个特殊的进程,主从库运行的同时,他也在运行。哨兵主要负责的就是三个任务:监控、选主和通知。
1.监控
哨兵在运行的时候,周期性地给所有的主从库发送PING命令,检测他们是否仍然在在线运行。如果从库没有在规定时间响应哨兵的PING命令,哨兵就会把从库标记为“下线状态”;同理,如果主库没有在规定时间响应哨兵的PING命令,哨兵就会判定主库下线,然后开始自动选主流程。
2.选主
哨兵就会从很多的从库里,按照一定的规则选择一个从库实例,把它作为新的主库。这一步完成之后,现在的集群里就又了新的主库。
3.通知
最后哨兵会把新的主库连接信息发送给其他从库,让他们执行replicaof命令,和新的主库连接,并进行数据的复制。同时,哨兵会把新主库的连接信息通知给客户端,让他们把请求发送到新主库上。

通知任务相对比较简单,哨兵只需要把新主库信息发给从库、客户端。让他们与新主库建立连接就行,不涉及决策的逻辑。但是,在监控和选主中,哨兵需要做出两个决策;

  • 监控,判定主库是否下线状态
  • 选主,哨兵要选择哪个从库作为主库

哨兵判断主观下线和客观下线

哨兵会使用PING命令来检测自己和主、从库的网络连接情况,用来判断实例的状态。如果哨兵发现主库和从库PING命令的响应超时了,那么,哨兵就会把它标记为“主观下线”。
如果哨兵判定的是从库,一般对外的业务影响不大。集群对外的服务也不会间断。如果检测的主库“主观下线”,开启主从切换,有一种可能存在,这次判断主库的网络访问压力大,没有及时响应。这样就造成了误判。
一旦哨兵判断主库下线了,会开始切换主库,切换主库时,从库和新主库进行数据的同步,这个过程本身就在消耗开销,在误判的情况下主库本身就不需要切换,所以这个过程的开销就是没有价值的。我们需要减少误判。
在判断主库是否下线时,不能由一个哨兵决定,只有大多数的哨兵实例,都判断主库已经“主观下线”,主库才会标记为客观下线,这样也就解决了误判。

如何选定新主库

1.优先级最高的从库的分高:
用户可以通过配置slave-priority配置项,给不同的从库设计优先级。
2.和旧主库同步最接近的从库的分高。
主库会用master_repl_offset记录当前的最新写操作在repl_backlog_buffer中的位置,而从库会用slave_repl_offset这个记录当前的复制进度。
3.ID号小的从库得分高
在优先级和复制进度都相同的情况下,ID号最小的从库得分最高,会被选为新主库。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2天前
|
存储 Java 数据库连接
使用Java开发桌面应用程序
使用Java开发桌面应用程序
11 0
|
2天前
|
Java API 开发工具
java与Android开发入门指南
java与Android开发入门指南
8 0
|
2天前
|
分布式计算 负载均衡 Java
构建高可用性Java应用:介绍分布式系统设计与开发
构建高可用性Java应用:介绍分布式系统设计与开发
7 0
|
2天前
|
前端开发 安全 Java
使用Spring框架加速Java开发
使用Spring框架加速Java开发
5 0
|
2天前
|
前端开发 JavaScript Java
Java与Web开发的结合:JSP与Servlet
Java与Web开发的结合:JSP与Servlet
8 0
|
2天前
|
设计模式 算法 Java
设计模式在Java开发中的应用
设计模式在Java开发中的应用
14 0
|
3天前
|
监控 Java Maven
揭秘Java Agent技术:解锁Java工具开发的新境界
作为JDK提供的关键机制,Java Agent技术不仅为Java工具的开发者提供了一个强大的框架,还为性能监控、故障诊断和动态代码修改等领域带来了革命性的变革。本文旨在全面解析Java Agent技术的应用场景以及实现方式,特别是静态加载模式和动态加载模式这两种关键模式。
21 0
|
3天前
|
存储 Java 开发者
探索Java开发中触发空指针异常的场景
作为一名后端开发者在Java编程的世界中,想必大家对空指针并不陌生,空指针异常是一种常见而又令人头疼的问题,它可能会在我们最不经意的时候突然出现,给我们的代码带来困扰,甚至导致系统的不稳定性,而且最可怕的是有时候不能及时定位到它的具体位置。针对这个问题,我们需要深入了解触发空指针异常的代码场景,并寻找有效的方法来识别和处理这些异常情况,而且我觉得空指针异常是每个Java开发者都可能面临的挑战,但只要我们深入了解它的触发场景,并采取适当的预防和处理措施,我们就能够更好地应对这个问题。那么本文就来分享一下实际开发中一些常见的触发空指针异常的代码场景,并分享如何有效地识别和处理这些异常情况。
18 1
探索Java开发中触发空指针异常的场景
|
4天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
45 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
4天前
|
Java
三个可能的Java面试题
Java垃圾回收机制自动管理内存,回收无引用对象的内存,确保内存有效利用。多态性允许父类引用操作不同子类对象,如Animal引用可调用Dog的方法。异常处理机制通过try-catch块捕获和处理程序异常,例如尝试执行可能导致ArithmeticException的代码,catch块则负责处理异常。
25 9