版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
高频后端服务面试试题及答案1.线程池的核心参数有哪些?生产环境中如何合理配置?线程池的核心参数包括:corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(非核心线程空闲存活时间)、unit(时间单位)、workQueue(任务队列)、threadFactory(线程工厂)、handler(拒绝策略)。核心线程数决定了线程池的基础处理能力,通常根据任务类型(CPU密集型/IO密集型)设置:CPU密集型建议设为CPU核心数+1,避免上下文切换;IO密集型因线程常阻塞,可设为CPU核心数×2或更高。最大线程数需结合任务峰值负载,若队列已满且核心线程全忙,会创建非核心线程处理,需避免设置过大导致资源耗尽。任务队列常用有界队列(如ArrayBlockingQueue),防止无界队列(如LinkedBlockingQueue)导致OOM。拒绝策略需根据业务容忍度选择:AbortPolicy(直接抛异常,适合关键任务)、CallerRunsPolicy(调用者执行,降低提交速度)、DiscardPolicy(丢弃新任务)、DiscardOldestPolicy(丢弃最旧任务)。生产中需结合压测数据调整,例如电商大促时可动态调整最大线程数,配合监控(如线程池活跃度、队列积压量)做弹性扩缩。2.如何解决Java中多线程的可见性和有序性问题?可见性问题源于各线程本地缓存与主存的不一致,有序性问题源于编译器/CPU的指令重排序。Java内存模型(JMM)通过happens-before规则定义可见性约束,并提供volatile、synchronized、Lock等机制。volatile关键字通过内存屏障(LoadStore/StoreLoad)禁止特定重排序,且写操作立即刷新主存,读操作强制从主存读取,保证可见性和部分有序性(仅保证变量自身的有序,不保证代码块整体)。synchronized通过MonitorEnter/MonitorExit指令,在进入同步块时清空本地缓存,退出时刷新主存,保证原子性、可见性和有序性(同步块内代码视为一个整体,禁止与块外代码重排序)。Lock(如ReentrantLock)基于AQS实现,通过unlock时释放锁(唤醒等待线程)和lock时获取锁(强制从主存读取),同样保证可见性。实际开发中,若变量是状态标志(如线程终止标志),用volatile更轻量;若涉及复合操作(如i++),需用synchronized或Atomic类(基于CAS)保证原子性。3.说说AQS(AbstractQueuedSynchronizer)的核心原理和设计模式?AQS是Java并发包的基础同步框架,通过维护一个volatileintstate(同步状态)和一个CLH变体的双向同步队列(存储等待线程)实现锁机制。核心方法包括acquire(获取锁)、release(释放锁)、acquireShared(共享锁获取)、releaseShared(共享锁释放)。独占模式(如ReentrantLock):线程尝试通过tryAcquire(需子类实现)修改state,成功则获取锁;失败则封装为Node(包含线程、等待状态)加入队列尾部,通过park()阻塞,直到前驱节点释放锁时被unpark()唤醒。共享模式(如CountDownLatch):tryAcquireShared返回值>0表示可获取,否则入队等待,释放时通过doReleaseShared唤醒后续节点。AQS使用模板方法模式,将通用流程(如入队、阻塞)封装在基类,将具体状态变更逻辑(tryAcquire/tryRelease)留给子类实现,提高扩展性。例如ReentrantLock的NonfairSync子类重写tryAcquire,实现非公平锁的抢占逻辑;CountDownLatch的Sync子类重写tryAcquireShared,根据state是否为0判断是否放行。4.MySQL索引失效的常见场景有哪些?如何避免?索引失效场景包括:模糊查询以通配符开头(如LIKE'%abc'):无法使用前缀索引,需改用全文索引或调整查询方式(如反向存储+反向索引)。类型隐式转换:如字段为varchar却用数字查询(WHEREphone,会触发全表扫描,需保持查询条件与字段类型一致。复合索引未遵循最左匹配原则:如索引(a,b,c),查询条件无a(如WHEREb=1)或跳过a直接用b、c(如WHEREa=1ANDc=1),无法使用索引。使用函数或表达式操作索引列:如WHEREYEAR(create_time)=2023,会先对整列计算YEAR再比较,需改为范围查询(create_time>='2023-01-01'ANDcreate_time<'2024-01-01')。索引列参与逻辑运算(如>、<)且数据分布不均:若某列90%的值为NULL,对该列的ISNOTNULL查询可能因优化器认为全表扫描更高效而放弃索引。避免方法:通过EXPLAIN分析执行计划,检查key字段是否为NULL;设计复合索引时按查询频率和区分度排序(高频、高区分度在前);避免对索引列做计算或类型转换;对于模糊查询,若必须左匹配,可使用覆盖索引(如索引(col)并查询SELECTcolWHEREcolLIKE'abc%')。5.事务的隔离级别有哪些?各自解决什么问题?SQL标准定义了4种隔离级别,从低到高:读未提交(ReadUncommitted):允许读取其他事务未提交的修改,会导致脏读(读取到回滚的数据)。读已提交(ReadCommitted,RC):仅读取已提交的数据,解决脏读,但可能出现不可重复读(同一事务两次查询结果不同)。可重复读(RepeatableRead,RR,MySQL默认):保证同一事务内多次查询结果一致,通过MVCC(多版本并发控制)的快照读实现,解决不可重复读,但可能出现幻读(查询范围新增数据)。MySQL通过间隙锁(GapLock)+行锁(RecordLock)的Next-KeyLock机制,在RR级别下可避免幻读。串行化(Serializable):事务串行执行,通过锁表实现,解决所有并发问题,但性能最差。实际应用中,RC和RR最常用。RC适合对一致性要求不高但需高并发的场景(如日志系统);RR适合金融等需要强一致性的场景(如账户余额查询)。需注意MySQL的RR级别通过MVCC和Next-KeyLock实现,而Oracle的默认隔离级别是RC,仅通过语句级快照避免不可重复读。6.Redis的持久化机制有哪些?各自优缺点及生产环境如何选择?Redis提供RDB(快照持久化)和AOF(日志追加持久化),以及4.0版本引入的混合持久化(RDB+AOF)。RDB:通过bgsave命令(fork子进程)将当前内存数据快照写入磁盘。优点是文件紧凑(二进制格式)、恢复快;缺点是实时性差(默认每5分钟或1万次写操作触发),可能丢失最后一次快照后的所有数据。AOF:记录所有写操作命令(追加到aof文件),通过rewrite机制压缩冗余命令(如多次incr合并为set)。优点是数据完整性高(可配置每秒fsync,最多丢失1秒数据);缺点是文件体积大、恢复速度慢(需重放所有命令)。混合持久化:AOF重写时,将重写时刻的RDB快照和后续增量命令(AOF格式)写入新文件。兼顾RDB的紧凑和AOF的实时性,恢复时先加载RDB快照,再重放增量命令。生产环境选择:若允许少量数据丢失(如缓存场景),可仅用RDB(配置合理的快照频率);若需要高数据完整性(如会话存储),建议启用AOF(appendfsynceverysec)并开启混合持久化;高并发场景需监控AOF文件大小(避免过大影响rewrite性能),可通过auto-aof-rewrite-percentage(超过上次重写后大小的100%触发)和auto-aof-rewrite-min-size(最小重写文件大小)优化。7.如何解决Redis缓存击穿、穿透、雪崩问题?缓存击穿:热点key过期时,大量请求同时查询DB,导致DB压力骤增。解决方法:①热点key设置永不过期(逻辑过期,通过异步线程更新);②使用互斥锁(如Redis的setnx),仅允许一个线程查询DB并更新缓存,其他线程等待;③提前更新(监控热点key,在过期前主动刷新)。缓存穿透:查询不存在的数据(如id=-1),导致请求直接打到DB。解决方法:①缓存空值(查询DB无结果时,缓存null并设置短过期时间);②布隆过滤器(预先将所有可能的key存入布隆过滤器,查询前检查是否存在,不存在则直接返回);③参数校验(过滤非法请求,如id<0)。缓存雪崩:大量key同时过期或Redis宕机,导致请求集中涌入DB。解决方法:①分散过期时间(为key的过期时间添加随机值,避免集中失效);②多级缓存(本地缓存+Redis,减轻Redis压力);③限流降级(通过Hystrix等组件限制DB请求,保护核心服务);④高可用架构(Redis集群+哨兵,避免单点故障)。8.消息队列(如Kafka)如何保证消息不丢失?消息丢失可能发生在生产者、Broker、消费者三个环节:生产者丢失:发送消息未确认。解决:Kafka生产者设置acks=all(所有ISR副本确认),并开启重试(retries=Integer.MAX_VALUE);RabbitMQ启用发布确认(publisherconfirm)和返回机制(returncallback)。Broker丢失:消息未持久化或节点宕机。解决:Kafka设置min.insync.replicas≥2(至少2个同步副本),并启用unclean.leader.election.enable=false(禁止非ISR节点成为leader,避免数据丢失);RabbitMQ设置durable=true(队列和消息持久化),镜像队列(多副本)。消费者丢失:未处理完消息就确认。解决:Kafka关闭自动提交(mit=false),手动提交offset(处理完消息后调用commitSync());RabbitMQ关闭自动ACK(autoAck=false),处理成功后调用channel.basicAck(),失败时根据情况reject或nack(重新入队)。生产中需结合监控(如Kafka的ConsumerLag),确保消费进度正常;同时,关键消息可通过事务或消息表(记录消息状态)做补偿(如定时扫描未确认消息重新发送)。9.如何设计一个高并发的接口?需要考虑哪些方面?高并发接口设计需从限流、缓存、异步、降级、数据库优化等多维度入手:限流:防止过多请求压垮服务。常用算法有令牌桶(TokenBucket,限制平均速率)、漏桶(LeakyBucket,限制突发流量)、滑动窗口(更精确控制时间段内的请求数)。实现方式:Nginx层限流(limit_req_zone)、网关层(SpringCloudGateway的RequestRateLimiter)、应用层(GuavaRateLimiter)。缓存:减少DB访问。热点数据提前加载到Redis,使用本地缓存(Caffeine)缓存高频小数据;缓存失效时通过互斥锁或异步加载避免缓存击穿。异步:将非核心操作(如日志记录、消息通知)通过消息队列(Kafka/RabbitMQ)异步处理,缩短接口响应时间。降级:当服务负载过高时,屏蔽非关键功能(如返回默认值、简化页面),保证核心功能可用。可通过Hystrix或Sentinel配置熔断规则(错误率≥50%时熔断,5秒后尝试恢复)。数据库优化:分库分表(按时间或ID哈希拆分)、读写分离(主库写,从库读)、批量操作(批量插入/更新减少IO)、索引优化(覆盖索引避免回表)。幂等性:防止重复提交。通过唯一ID(如订单号)+幂等表(记录已处理的ID)实现,接口先查询幂等表,存在则直接返回结果。分布式锁:控制对共享资源的访问(如库存扣减),使用Redis的Redisson或ZooKeeper实现,避免超卖。例如,电商秒杀接口可设计为:前端限流(验证码/按钮防重复点击)→网关层限流(限制IP访问频率)→应用层检查库存(缓存中校验)→扣减库存(分布式锁+DB行锁)→异步提供订单(消息队列),确保在10万QPS下仍能稳定运行。10.单例模式的线程安全实现方式有哪些?各有什么优缺点?常见线程安全的单例模式实现:饿汉式:类加载时初始化实例。```javapublicclassSingleton{privatestaticfinalSingletonINSTANCE=newSingleton();privateSingleton(){}publicstaticSingletongetInstance(){returnINSTANCE;}}```优点:简单、线程安全(类加载机制保证);缺点:提前初始化,可能浪费资源(若实例使用频率低)。懒汉式(synchronized):```javapublicclassSingleton{privatestaticSingletonINSTANCE;privateSingleton(){}publicstaticsynchronizedSingletongetInstance(){if(INSTANCE==null){INSTANCE=newSingleton();}returnINSTANCE;}}```优点:延迟初始化;缺点:synchronized修饰方法,并发性能差(每次获取实例都加锁)。双重检查锁定(DCL):```javapublicclassSingleton{privatestaticvolatileSingletonINSTANCE;//防止指令重排序privateSingleton(){}publicstaticSingletongetInstance(){if(INSTANCE==null){//第一次检查,避免不必要的锁synchronized(Singleton.class){if(INSTANCE==null){//第二次检查,防止多线程同时通过第一次检查INSTANCE=newSingleton();}}}returnINSTANCE;}}```优点:延迟初始化、线程安全、性能高(仅首次创建加锁);缺点:需volatile修饰INSTANCE(避免JVM指令重排序导致其他线程获取到未初始化的实例)。静态内部类:```javapublicclassSingleton{privateSingleton(){}privatestaticclassHolder{staticfinalSingletonINSTANCE=newSingleton();}publicstaticSingletongetInstance(){returnHolder.INSTANCE;}}```优点:利用类加载的延迟性(Holder类在第一次调用getInstance时加载),线程安全(类加载机制保证),无需加锁;缺点:无法传递参数(若单例需要参数初始化,不适用)。生产中推荐DCL或静态内部类,DCL适用于需要参数的场景,静态内部类更简洁。11.如何设计一个分布式锁?需要考虑哪些问题?分布式锁需满足:互斥性(同一时刻仅一个客户端持有)、可重入性(同一客户端可多次加锁)、高可用(部分节点宕机仍可用)、容错性(锁自动过期避免死锁)、正确释放(客户端崩溃时锁能被释放)。常用实现方案:Redis(Redisson):通过set命令(setkeyvalueNXPX30000)原子操作加锁,value设为客户端唯一标识(如UUID+线程ID)保证可重入(通过hash结构记录加锁次数);释放时检查value是否匹配(避免释放其他客户端的锁),使用Lua脚本保证原子性(查询+删除)。ZooKeeper:创建临时有序节点(/lock/seq-),客户端监听前一个节点的删除事件,前一个节点删除则当前节点获得锁;临时节点在客户端断开时自动删除,避免死锁。设计时需考虑:锁过期时间:需大于业务执行时间(如设置30秒),若业务耗时较长,需自动续期(Redisson的WatchDog机制每10秒续期到30秒)。锁的可重入:记录客户端标识和加锁次数,重入时增加计数,释放时减少。避免误删:释放锁时必须验证持有方身份(如Redis的value匹配),防止A客户端的锁被B客户端误删(如A执行时间过长导致锁过期,B加锁后A释放)。集群模式:Redis主从架构下,主节点宕机可能导致锁丢失(未同步到从节点),可使用Redlock算法(向多个独立Redis实例加锁,多数成功则认为加锁成功)提高可靠性,但性能较低。12.微服务拆分的原则和常见问题有哪些?微服务拆分原则:单一职责:每个服务专注一个业务功能(如用户服务、订单服务),避免大而全的“单体服务”。边界清晰:通过领域驱动设计(DDD)划分限界上下文(BoundedContext),服务间通过API或消息队列通信,避免共享数据库。高内聚低耦合:服务内部逻辑高度相关,服务间依赖通过接口抽象(如Feign),减少直接依赖。可独立部署:每个服务有独立的代码库、构建流程,可单独发布(如Docker容器化)。常见问题及解决:服务间调用复杂:引入服务网关(如SpringCloudGateway)统一路由、鉴权;使用服务注册发现(Eureka/Nacos)管理服务地址;通过分布式追踪(Sleuth+Zipkin)监控调用链路。数据一致性:跨服务的事务无法通过本地事务保证,需用最终一致性方案(TCC补偿、消息事务、Saga模式)。例如,订单服务创建订单后,通过消息队列通知库存服务扣减库存,若扣减失败,订单服务回滚(消息事务需保证消息发送和本地事务原子性)。运维复杂度高:使用K8s进行容器编排(自动扩缩容、故障恢复);日志集中管理(ELK);监控告警(Prometheus+Grafana)。接口版本兼容:API需设计成向后兼容(如添加新字段不影响旧版本),使用版本号(/api/v1/...)或内容协商(Accept头)管理。13.如何优化慢SQL?具体步骤是什么?优化慢SQL需结合执行计划和业务场景,步骤如下:1.定位慢SQL:通过MySQL的慢查询日志(slow_query_log)或监控工具(如PerconaToolkit的pt-query-digest)抓取执行时间超过阈值(如1秒)的SQL。2.分析执行计划:使用EXPLAIN命令查看type(访问类型,理想为ref或eq_ref)、key(使用的索引)、rows(扫描行数)、Extra(是否Usingfilesort/Usingtemporary)。3.检查索引:缺失索引:对WHERE、JOIN、ORDERBY、GROUPBY中的列添加索引(注意复合索引的最左匹配)。冗余索引:删除重复或包含的索引(如已有(a,b),无需单独(a))。索引失效:避免对索引列做计算、类型转换,优化LIKE查询(避免左通配符)。4.优化查询逻辑:避免SELECT:只查询需要的列,减少数据传输和回表(若查询列都在索引中,使用覆盖索引)。分页优化:大数据量分页(如LIMIT100000,20)时,避免全表扫描,改用覆盖索引+子查询(如SELECTFROMtWHEREid>(SELECTidFROMtLIMIT100000,1)LIMIT20)。减少JOIN表数量:拆分为多个单表查询(通过缓存或本地查询),或调整表结构(适当冗余字段)。5.调整数据库配置:增大innodb_buffer_pool_size(缓冲池大小,建议占内存50%-70%),减少磁盘IO。调整innodb_flush_log_at_trx_commit(若允许少量数据丢失,设为2,提高写性能)。6.定期维护:分析表(ANALYZETABLE)更新统计信息,帮助优化器选择更优索引。重建索引(ALTERTABLEtENGINE=InnoDB)或优化表(OPTIMIZETABLE),减少索引碎片。例如,某慢SQL为SELECTFROMorderWHEREuser_id=123ANDstatus=1ORDERBYcreate_timeDESCLIMIT10,执行计划显示type=ALL(全表扫描),rows=100000。优化方法:添加复合索引(user_id,status,create_time)(最左匹配user_id和status,包含create_time排序),使查询变为索引扫描(type=ref),rows=100,性能提升显著。14.如何保证接口的幂等性?常见实现方式有哪些?幂等性指同一请求多次调用,结果与调用一次一致。常见实现方式:唯一标识(Token):客户端提供唯一ID(如UUID),随请求发送。服务端通过幂等表(如redis或DB)记录已处理的ID,重复请求直接返回结果。例如,支付接口要求携带out_trade_no,服务端查询该号是否已支付,已支付则返回成功。数据库唯一约束:通过唯一索引(如订单号、业务流水号)防止重复提交。插入时若违反唯一约束,捕获异常并返回已存在的结果。状态机:业务状态按顺序变更(如订单状态:未支付→已支付→已发货),仅允许从低状态到高状态变更。例如,重复调用“支付”接口,若订单已支付,直接返回成功。乐观锁:通过版本号(version)或时间戳实现。更新时检查版本号,若与当前版本一致则更新并递增版本,否则重试或返回失败。例如:```sqlUPDATEorderSETamount=100,ve
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年中国古典文学名著导读题库含故事情节解析
- 2026年建筑工程施工安全标准知识测试模拟题
- 2026年建筑结构设计与施工安全考核题
- 2026年旅游景区管理安全规定模拟卷
- 2026年汽车维修专业技能提升测试题集
- 2026年人力资源管理专业知识点考试题集
- 2026年法律条文解释与问答390题
- 2026年汽车维修技术检测题汽车电路故障诊断与修复
- 2026年生物信息学基础与基因数据分析练习题
- 2026年建筑结构设计初级考试模拟卷
- 2026年各地高三语文1月联考文言文汇编(文言详解+挖空)
- 2026年春季统编版三年级下册小学语文教学计划(含进度表)
- 家庭医生签约服务工作实施方案
- 冰箱安装施工方案
- 村委安全生产责任制度
- 2025-2030中国碳酸氢钠市场未来前瞻及投资战略规划策略建议研究报告
- 土石方开挖与回填施工方案
- 2025年12月广西区一模语文2025-2026年度首届广西职教高考第一次模拟考试2026年广西高等职业教育考试模拟测试语文含逐题答案解释99
- 2026元旦主题班会:马年猜猜乐猜成语 (共130题)【课件】
- 2026年盘锦职业技术学院单招职业技能测试题库及参考答案详解一套
- 湖北省2024-2025学年高二上学期期末考试英语含答案
评论
0/150
提交评论