快手商业化 Java后端 二面|面试官很nice

news2024/9/23 7:32:01

在这里插入图片描述

面试总结:没有那种纯八股问题,都是偏向于情景题。看到面试官最后出了一道多叉树的题目,我以为是想直接刷人,但还是尽力去尝试了一下,最后也没做出来,面试官很nice,在答不上来的时候会引导我去思考,并在我回答正确的时候给与充分的肯定。


1.线程池工作过程

线程池的工作过程主要包括以下几个步骤:

(1) 线程池创建时会初始化一定数量的核心线程,等待任务。

(2) 当有新任务提交时,会首先判断当前运行的线程数是否小于核心线程数。如果小于,则创建新的线程来执行任务。

(3) 如果当前运行的线程数大于或等于核心线程数,则将任务放入队列中等待执行。

(4) 如果队列已满,且当前线程数小于最大线程数,则创建新的线程来执行任务。

(5) 如果队列已满,且当前线程数等于最大线程数,则执行拒绝策略。

(6) 当线程完成任务时,会从队列中取出新的任务来执行。

(7) 当线程空闲时间超过keepAliveTime,如果当前运行的线程数大于核心线程数,则这些线程会被停止。

2.线程回收机制

线程池的线程回收机制主要依赖于线程池的工作队列和keepAliveTime参数:

(1) 当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直到线程池中的线程数不超过corePoolSize。

(2) 如果设置了allowCoreThreadTimeOut(true),则核心线程在空闲时间超过keepAliveTime后也会被回收。

(3) 线程池使用一个HashSet存储工作线程的引用,在工作线程退出时,它会被从线程池中移除。

(4) 在ThreadPoolExecutor的getTask()方法中,如果线程获取任务时超时,说明该线程可以被回收。

(5) 线程回收的过程是通过线程自己执行完run方法来实现的,而不是由外部强制中断。

这种机制可以在执行大量短期异步任务时,提高线程的复用性,避免频繁创建和销毁线程带来的开销。

3.为什么标记核心线程和非核心线程

区分核心线程和非核心线程主要有以下几个原因:

(1) 资源管理:核心线程代表了线程池在空闲时刻的最小线程数,可以保证线程池的快速响应能力。

(2) 性能优化:核心线程通常不会被回收,可以减少线程创建和销毁的开销。

(3) 弹性伸缩:通过调整核心线程数和最大线程数,可以实现线程池的动态伸缩,适应不同的负载情况。

(4) 任务优先级:核心线程可以优先处理任务,非核心线程则在任务量增大时才会被创建。

(5) 资源控制:可以通过控制核心线程数来限制系统资源的使用,避免创建过多线程导致系统负载过高。

这种设计使得线程池可以在保证基本性能的同时,根据实际负载情况动态调整,既保证了响应速度,又避免了资源浪费。

4.数据库相关的查询优化

数据库查询优化是一个复杂的话题,主要包括以下几个方面:

(1) 索引优化:

  • 为常用查询字段创建适当的索引
  • 避免过多索引,可能影响插入和更新性能
  • 使用复合索引时注意最左前缀原则
  • 避免在索引列上使用函数或进行运算

(2) SQL语句优化:

  • 避免使用SELECT *,只查询需要的字段
  • 使用EXPLAIN分析SQL执行计划
  • 善用LIMIT语句来限制结果集大小
  • 使用合适的JOIN方式(INNER JOIN, LEFT JOIN等)

(3) 表结构优化:

  • 选择合适的数据类型,如使用UNSIGNED INT代替INT
  • 适当进行表的垂直拆分或水平拆分
  • 使用合适的存储引擎(如InnoDB支持事务,MyISAM适合只读场景)

(4) 架构优化:

  • 使用读写分离
  • 采用分库分表策略
  • 使用缓存层(如Redis)减轻数据库压力

在实际优化中,需要根据具体的业务场景和查询模式来选择合适的优化策略。

5.Redis主从集群相关问题

(1) 主从复制机制:

  • 全量复制:slave首次连接master时,master会生成RDB文件发送给slave
  • 增量复制:master将新的写命令异步发送给slave
  • 断点续传:当主从连接断开后,可以从断点处继续复制

(2) 数据一致性问题:

  • Redis采用异步复制,可能存在数据不一致的情况
  • 可以通过wait命令来实现同步复制,但会影响性能

(3) 故障转移:

  • 使用Sentinel进行自动故障检测和转移
  • Sentinel通过投票机制选举新的master

(4) 读写分离:

  • 可以将读请求分发到slave节点,减轻master压力
  • 需要考虑数据一致性问题,可能读到旧数据

(5) 数据过期问题:

  • 主节点负责key的过期删除
  • 从节点不会主动删除过期key,而是等待主节点的DEL命令

(6) 数据持久化:

  • 主节点通常配置AOF持久化,从节点可以只配置RDB持久化
  • 需要权衡数据安全性和性能

在实际应用中,需要根据业务需求和系统规模来设计合适的Redis集群架构。

7.项目中比较精彩的点

缓存优化的考量

(1) 缓存预热:

  • 系统启动时,提前将热点数据加载到缓存中
  • 可以通过定时任务或者手动触发来实现

(2) 缓存更新策略:

  • 实现缓存和数据库的双写一致性
  • 可以采用先更新数据库,再删除缓存的策略
  • 使用消息队列来保证最终一致性

(3) 缓存穿透优化:

  • 对不存在的key也缓存null值,并设置较短的过期时间
  • 使用布隆过滤器来快速判断key是否存在

(4) 缓存击穿优化:

  • 对热点key使用互斥锁或分布式锁
  • 实现请求合并(hystrix request cache)

(5) 缓存雪崩优化:

  • 给缓存的失效时间添加随机值
  • 实现熔断机制,当缓存失效量突增时,暂停使用缓存

(6) 缓存降级:

  • 当缓存服务不可用时,直接返回默认值或旧数据
  • 实现服务降级,保证核心功能可用

8.缓存优化的细节

针对缓存优化的细节,可以从以下几个方面深入讨论:

(1) 缓存key的设计:

  • 使用有意义的前缀,便于管理和查找
  • 考虑key的长度,过长的key会增加内存使用
  • 对于复杂对象,可以使用哈希算法生成key

(2) 缓存粒度:

  • 细粒度缓存:缓存具体字段,减少缓存内容,但增加缓存操作次数
  • 粗粒度缓存:缓存整个对象,减少缓存操作,但可能缓存无用数据

(3) 缓存有效期:

  • 根据数据更新频率设置合适的过期时间
  • 对不同类型的数据设置不同的过期策略
  • 考虑使用滑动过期时间(每次访问都刷新过期时间)

(4) 缓存预加载:

  • 识别热点数据,在系统启动时预加载
  • 实现智能预加载,根据访问模式动态调整预加载策略

(5) 缓存更新机制:

  • 实现缓存更新的重试机制
  • 使用分布式锁来保证并发更新的正确性
  • 考虑使用异步更新来提高性能

(6) 缓存数据一致性:

  • 实现最终一致性策略,如延迟双删
  • 使用版本号机制来处理并发更新
  • 考虑使用 Canal 等工具实现数据库和缓存的同步

这些细节需要在实际应用中不断调优和验证,以达到最佳的性能和可靠性。

9.设计消息队列(MQ)

设计一个消息队列系统需要考虑很多方面,以下是一些关键点:

(1) 消息存储:

  • 使用高性能的存储引擎,如 RocksDB 或自研的 LSM 树存储引擎
  • 实现分段日志(Log Segment)存储方式,便于清理过期数据
  • 考虑内存映射文件(Memory Mapped File)提高I/O性能

(2) 高可用性:

  • 实现主从复制机制,保证数据不丢失
  • 设计 RaftPaxos 等一致性协议,实现leader选举
  • 实现故障自动转移(Failover)机制

(3) 高吞吐量:

  • 使用零拷贝(Zero-Copy)技术减少数据复制
  • 实现批量发送和消费机制
  • 使用异步I/O提高并发性能

(4) 消息可靠性:

  • 实现消息确认(ACK)机制
  • 支持消息重试和死信队列
  • 实现幂等消费,处理重复消息

(5) 扩展性:

  • 设计分区(Partition)机制,支持横向扩展
  • 实现动态扩缩容能力
  • 支持多数据中心部署

(6) 消息顺序性:

  • 实现分区内的顺序消费
  • 支持全局顺序消费的特性

(7) 消息模型:

  • 支持发布/订阅模型
  • 支持点对点队列模型
  • 考虑支持延迟队列、优先级队列等特性

(8) 客户端SDK:

  • 设计简单易用的API
  • 实现自动重连、负载均衡等特性
  • 支持多种编程语言

实际情况还需要根据具体需求和场景进行取舍和优化。

11.使用消息队列的好处

(1) 异步处理:

  • 将耗时操作异步化,提高系统响应速度
  • 实现生产者和消费者的解耦,提高系统灵活性

(2) 流量削峰:

  • 缓冲突发流量,保护后端系统
  • 实现请求的平滑处理,提高系统稳定性

(3) 解耦系统:

  • 降低系统间的直接依赖
  • 提高系统的可扩展性和可维护性

(4) 扩展性:

  • 易于横向扩展,提高系统处理能力
  • 支持动态扩缩容,适应业务变化

(5) 可靠性投递:

  • 保证消息至少被消费一次
  • 支持消息重试机制,提高系统容错能力

(6) 顺序保证:

  • 在特定场景下保证消息的顺序性
  • 满足某些业务的顺序处理需求

(7) 流量控制:

  • 实现背压(back-pressure)机制
  • 控制消息生产和消费的速率,保护系统

(8) 事务消息:

  • 支持分布式事务
  • 保证跨系统操作的一致性

12.Redis使用场景

(1) 缓存:

  • 热点数据缓存,减轻数据库压力
  • 页面缓存,提高网站访问速度

(2) 计数器:

  • 高并发计数,如文章阅读量、点赞数
  • 限流计数,实现接口访问频率控制

(3) 分布式锁:

  • 实现跨进程、跨服务器的互斥操作
  • 控制并发访问,保证数据一致性

(4) 会话存储:

  • 存储用户会话信息,实现分布式 Session
  • 提高系统可扩展性,便于水平扩展

(5) 排行榜:

  • 使用Sorted Set实现实时排行榜
  • 高效的数据结构,支持大规模数据

(6) 消息队列:

  • 利用List实现简单的消息队列
  • 适用于轻量级的异步任务处理

(7) 分布式ID生成:

  • 利用INCR命令实现全局唯一ID
  • 高性能,适用于高并发场景

(8) 布隆过滤器:

  • 使用Bitmap实现布隆过滤器
  • 用于大规模数据的快速判重

(9) 延迟队列:

  • 利用Sorted Set实现延迟任务
  • 用于定时任务、订单超时处理等场景

13.Redis实现分布式锁

Redis 实现分布式锁的基本步骤如下:

(1) 获取锁: 使用 SETNX 命令尝试设置一个键值对,如果键不存在则设置成功并获得锁:

(2) 设置过期时间: 为了防止客户端崩溃导致锁无法释放,需要设置过期时间

(3) 执行业务逻辑

(4) 释放锁: 使用 Lua 脚本保证原子性,只有持有锁的客户端才能释放锁:

注意事项:

  • 使用唯一值标识锁的持有者,防止误释放
  • 设置合理的过期时间,避免死锁
  • 考虑使用 Redisson 等成熟的实现,它们提供了自动续期等高级特性

这种实现方式适用于简单场景,但在高并发或对可靠性要求较高的场景下,建议使用Redisson等专业的分布式锁实现。

15.普通 Redis 锁与 Redisson 的区别

Redisson 是一个在 Java 客户端上使用 Redis 的工具库。它提供了一个易于使用且强大的一套 API,来简化分布式系统的开发。Redisson 提供了多种分布式锁机制,比如公平锁、读写锁、红锁等,适合各种不同的场景,帮助开发者解决并发控制问题。

redis 锁的局限性

  1. 单Redis实例
    • 这种锁机制在单一 Redis 实例环境下工作良好,但在集群环境下可能会面临问题。
  2. 没有自动续期
    • 锁的持有者必须自己管理锁的续期,以防锁被意外释放。
  3. 原子性限制
    • 在解锁时需要小心,因为 DEL 命令在分布式系统中可能会删除不是自己设置的锁。

Redisson 锁

  1. 更高层次的抽象
    • Redisson 提供了类似 Java 原生 java.util.concurrent.locks.Lock 接口的抽象,让使用锁变得更加自然和简单。
  2. 内置功能
    • 公平锁、读写锁、可重入锁、红锁(一种分布式环境下的锁)等多种锁实现。
    • 内置续期机制:锁的持有者可以自动续期,防止锁误释放。

Redisson 锁的优势

  1. 适用性广
    • 同时适用于单实例和分布式集群环境,可以处理更复杂的分布式锁需求。
  2. 简化开发
    • 提供了接口级别的锁实现,更易于集成到现有项目中,并支持自动续期和更复杂的锁策略。
  3. 高可用性
    • 支持 Redis 的集群、哨兵模式和主从模式,提供高可用性。

16.Redission 相关问题

(1) 是否会产生死锁

Redisson 锁在设计上考虑到避免死锁。它通过设置锁的过期时间和自动续期机制来防止持有锁的节点意外崩溃或长时间失去响应从而导致死锁。

(2) Redisson 锁如何实现

  • 获取锁: 使用 Redis 的 SET 命令加上 NX(不存在时设置)和 PX(过期时间)参数来实现原子操作,从而确保只有一个客户端能够成功获得锁。
  • 释放锁: Redisson 使用 Lua 脚本来确保释放锁操作的原子性,即只有持有锁的客户端才能释放锁。
  • 自动续期: Redisson 提供了 Watchdog(看门狗)机制,一旦锁被某个客户端获取,Redisson 会启动一个后台线程,定期延长锁的过期时间,避免锁因为超时而被自动释放。

(3) 过期时间的作用及默认值

过期时间的作用是防止在锁持有者发生意外崩溃或长时间失去响应时,锁一直存在而导致其他客户端无法获得锁。过期时间确保了锁最终会在一段时间后自动释放,从而避免死锁。

Redisson 默认的锁过期时间是 30 秒。这意味着如果没有特殊配置,Redisson 锁在持有之后,如果不进行操作,30秒后会自动释放。

(4) 自动续期机制

Redisson 的自动续期机制依靠一个叫做 Watchdog(看门狗)的后台线程来实现。当一个客户端成功获取到锁时,一个后台的 Watchdog 线程会启动,默认每隔10秒执行一次续期操作,将锁的过期时间延长一定周期,以此确保持有锁的客户端在执行长时间任务时不会因为锁的过期而失去锁。


更多惊喜

我还将定期分享:

  • 最新互联网资讯:让你时刻掌握行业动态。

  • AI前沿新闻:紧跟技术潮流,不断提升自我。

  • 技术面试与职业发展:助你在职业生涯中走得更远、更稳。

  • 程序员生活趣事:让你在忙碌的工作之余找到共鸣与乐趣。

关注回复【1024】惊喜等你来拿!

敬请关注【程序员世杰】

点击关注程序员世杰

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1966762.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

煤矿行业智慧矿山信息化解决方案

文章摘要 煤矿行业背景概述煤炭行业经历了从普通机械化到自动化的跨越,目前正向智能化发展。尽管煤矿智能化尚处于起步阶段,但智能化程度正不断进步。 煤矿信息化发展趋势信息化发展趋势从单机自动化监控系统,发展到全矿井综合自动化系统&am…

【算法】斐波那契查找(黄金分割查找)

原理 斐波那契查找的原理与二分查找、插值查找相似,仅仅是改变了中间节点(mid)的位置,mid 不再是中间或插值得到的,而是位于黄金分割点的附近,即 mid low F(k-1)-1 (F代表斐波那契数列&#…

Java 应用中的内存泄漏:常见场景及最佳实践

内存泄漏是 Java 应用程序中一个常见而棘手的问题,它会导致应用程序的内存使用不断增长,最终影响性能和稳定性。尽管 Java 提供了垃圾回收机制来自动管理内存,但内存泄漏问题依然普遍存在。内存泄漏的根源可能包括不再使用的对象仍被持有引用…

第四范式上线搜广推一体化平台 赋能企业高效增长

产品上新 Product Release 今天,第四范式产品再度上新,正式升级并推出的“搜广推”一体化平台——天枢。 天枢拥有全面的用户画像分析、端到端的搜索推荐一体化、一站式流量运营管理等能力,集合智能搜索、智能推荐和智能推广三大能力于一身&a…

酷柚易汛ERP全新功能插件上线“业绩提成”很多老板期待已久,终于来啦!

业绩提成基于进销存系统销货业务设计的、用于自动化处理业务员销货业绩与提成计算过程的插件,汇总累计进销存系统产生的业绩额度并根据自定规则计算对应提成金额,以减少人力计算成本 多场景适配 集成了常用的提成方式,并且可设置提成额度限…

启动 /使用/关闭 Redis 服务器

1. Linux 启动 Linux 系统启动 Redis 有两种方法,分别是前台启动,后台启动,两者各有差异; (1)前台启动 首先,需要进入 bin 路径(安装路径不同输入的命令也不同); 个人的命令(一般…

Ubantu中Docker-Compose的安装与卸载

文章目录 一、卸载二、安装安装Docker-Compose添加权限验证 一、卸载 sudo rm /usr/local/bin/docker-compose二、安装 安装Docker-Compose curl -L https://github.com/docker/compose/releases/download/1.21.1/docker-compose-uname -s-uname -m -o /usr/local/bin/docke…

【Python正则-驯化】一文学会通过Python中的正则表达式提取文本中的日期

【Python正则-驯化】一文学会通过Python中的正则表达式提取文本中的日期 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 免费获取相关内容…

吴恩达机器学习-C1W3L2-逻辑回归之S型函数

可选实验:逻辑回归 在这个不评分的实验中,你会 探索sigmoid函数(也称为logistic函数)探索逻辑回归;哪个用到了s型函数 import numpy as np %matplotlib widget import matplotlib.pyplot as plt from plt_one_addpt_onclick import plt_one_addpt_onclick from l…

java远程调试

java远程调试 idea2024创一个Spring Web项目springdemo1 使用maven-assembly-plugin插件打包成JAR文件 pom.xml参考如下 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi&quo…

【C#之WPF,给Border设置背景图片,代码运行后图片无法显示】

C#之WPF&#xff0c;给Border设置背景图片&#xff0c;代码运行后图片无法显示 方案 方案 选中你的图片找到属性&#xff1b; 这两个都改一下&#xff1b; 改好之后在运行就可以正常显示了。

uni-app中使用支付宝扫码插件并且在真机调试时使用(详细教程)

前言&#xff1a;uni-app自带的扫码api 识别不灵敏&#xff0c;每次都得扫很长时间且不断调整才能扫出来码&#xff0c;所以决定使用支付宝扫码插件&#xff0c;官方插件地址&#xff1a;https://ext.dcloud.net.cn/plugin?id2636#detail 使用步骤: 1、下载插件到项目中 2、…

ai绘画软件哪个好?5个工具让你绘图快人一步

最近&#xff0c;沉浸式感受火把节的体验在网上引起了广泛关注&#xff0c;成为了热门话题。然而&#xff0c;我们这些忙碌的打工人&#xff0c;因为工作繁忙&#xff0c;只能羡慕地看着别人分享的欢乐瞬间。 别灰心&#xff01;谁说我们不能以另一种方式参与这场盛宴呢&#…

4款免费且安全:常用的PDF转Word在线转换工具推荐

现在办公越来越离不开电脑了&#xff0c;PDF文件和Word文档来回转换的需求也越来越大。作为一个天天跟文件打交道的上班族&#xff0c;我特别明白找个好用、靠谱的PDF转Word在线转换工具有多重要。今儿个&#xff0c;给大家说说五个免费的转换工具&#xff0c;都是我试过觉得挺…

SPSSAU | CatBoost模型原理及案例实操分析

CatBoost 是一种基于梯度提升的决策树(Gradient Boosting Decision Trees, GBDT)算法&#xff0c;专门优化了处理分类特征和序列数据的能力。算法步骤如下&#xff1a; 第一&#xff1a;生成初始模型&#xff0c;从简单的模型开始&#xff0c;通常是所有目标值的平均值&#x…

telnet与ping:测试IP及端口连通性

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 python使用API实现…

压路机土方压实摊铺精确施工引导系统

整体架构 一、土方压实摊铺工程现状 二、整体介绍 1、在施工现场利用 GNSS 定位设备终端、振动传感器、温度传感器&#xff0c;实现对施工机械的位置、运行状态实时监测&#xff0c;实现底层数据的多参数、多种类高效采集。 2、本系统基于卫星差分定位技术&#xff0c;通过与…

JNPF全新V5.0版本!重磅升级——协同办公篇

尊敬的JNPF用户们&#xff1a; 我们非常高兴地宣布&#xff0c;经过团队数月的辛勤努力和不断的技术创新&#xff0c;JNPF快速开发平台终于迎来了里程碑式的全新升级——V5.0版本&#xff01;这一版本的更新发布&#xff0c;不仅代表着我们技术实力的进一步提升&#xff0c;是…

点线面的智慧:转转JTS技术如何塑造上门履约地理布局

1 引言 如上图所示&#xff0c;在转转上门履约的场景中&#xff0c;上门服务的覆盖区域是在地图上画电子围栏来划定的。这就涉及到一些几何图形的操作和空间关系判断&#xff0c;其中最核心问题就是要解决如何判断位置是否在上门覆盖范围内。下面介绍下 JTS&#xff0c;以及如何…

微服务实战系列之玩转Docker(八)

前言 “Compose”一词的原意是创作、组成、构成&#xff08;一个整体&#xff09;&#xff0c;那么“Docker Compose”一词可以理解为一组docker。今天博主着重介绍一下这个“容器导演” —— 一个docker自带的容器管理工具。 Docker Compose入门 1. 定义 Docker Compose is …