回答重点1)先分析业务需求:
确定数据量及增长趋势,评估分库分表的必要性。(需要一定的预判但是不要过度设计)
2)设计分库分表方案:
选择适合的分库和分表策略(水平、垂直、哈希、范围等),并规划分库分表的结构。
3)实现数据路由:
根据分库分表策略设计数据路由机制,一般通过应用层代码或数据库中间件来实现,将请求路由到相应的数据库或表。
4)数据迁移:
将现有数据迁移到新的分库分...
回答重点1)首先是事务的问题。
我们使用关系型数据库,有很大一点在于它保证事务的完整性。
而分库之后单机事务就用不上了,必须使用分布式事务来解决,而分布式事务相对而言就比较重了,而且大部分的分布式事务只能保证最终一致性,所以业务上会存在数据不一致的场景。
2)连表 JOIN 问题
在一个库中的时候我们还可以利用 JOIN 来连表查询,而跨库了之后就无法使用 JOIN 了。
此时的解决方案就是...
回答重点在 MySQL 中,获取数据并不总是直接从磁盘读取。MySQL 使用缓存机制,比如 InnoDB 存储引擎,会将常用的数据和索引缓存在内存中,以提高读取性能。当查询数据时,系统首先会检查缓存(如缓冲池),如果数据存在于内存中,则直接从内存中读取;如果不在,则会从磁盘读取并加载到缓存中。
扩展知识MySQL 中的缓存MySQL 从缓存中读取所指的缓存,实际上包含了两个缓存:
1)查询缓...
回答重点MySQL 的 Doublewrite Buffer 是 InnoDB 存储引擎中的一个机制,用于确保数据的安全性和一致性。其作用是将数据首先写入一个内存缓冲区(双写缓冲区),然后再将其写入数据文件。这种方式可以防止在写入过程中因崩溃或故障导致数据损坏,确保数据的一致性和完整性。
工作原理简述:
写入流程:当事务提交时,InnoDB 首先将数据写入 Doublewrite Buff...
回答重点MySQL 中的 Log Buffer 是一个内存区域,用于暂时存储事务日志(redo log)的数据。在 InnoDB 存储引擎中,它的主要作用是提高性能,通过批量写入操作将日志数据从内存中写入磁盘,减少磁盘 I/O 操作的频率。
扩展知识进一步理解 Log Buffer我们来看一下官网的一张图:
我们看看 Log Buffer。从上面的图我们可以得知,它是 redo...
回答重点性能问题:
多表 JOIN 可能导致查询性能下降,尤其是在处理大数据集时,JOIN 操作的计算复杂度会显著增加,需要进行大量的数据扫描和匹配,增加了内存和CPU的消耗,导致响应时间变长。
可读性和维护性:
多表 JOIN 的查询语句较为复杂,降低了 SQL 的可读性和可维护性。复杂的语句可能会增加错误发生的概率,使得后续的调试和优化更加困难。
扩展知识多表 JOIN这里的多表...
回答重点可以利用 MySQL 自带的 slow_query_log 来监控慢 SQL,它是 MySQL 提供的一个日志功能,用于记录执行时间超过特定阈值的 SQL 语句。
对于慢查询,再使用 EXPLAIN 分析执行计划,查看查询的执行顺序、使用的索引、扫描的行数等,以识别潜在的性能瓶颈。
基于 EXPLAIN 再进行针对性的优化,常见的优化方向有:
根据 EXPLAIN 的结果,检查是否...
回答重点优化方式可以有三种:
1)子查询
比如 select * from mianshiya where name = ’yupi‘ limit 99999990,10; 这样的一条查询语句,可以优化成:
12345select * from mianshiya where name = 'yupi' and id >= (select id from mians...
回答重点INNER JOIN:
只返回两个表中匹配的行。如果没有匹配,则该行不会出现在结果集中。
适用于只关心交集数据的场景。
LEFT JOIN(或 LEFT OUTER JOIN):
返回左表中的所有行,即使右表中没有匹配的行。如果右表没有匹配,则结果中的右侧列会显示为NULL。
适用于需要保留左表所有数据的场景。
RIGHT JOIN(或 RIGHT OUTER JOIN):
...
回答重点在 MySQL 的 InnoDB 存储引擎中,B+ 树默认数据页大小为 16KB。
参数:
每个节点页大小为 16KB(即 16384 字节)。
假设每个数据记录的主键和数据大小为 1KB(一般会比这个小,但这里取整方便计算)。
每个内部节点(非叶子节点)存储的是指向子节点的指针和索引键。
三层 B+ 树的存储计算:
叶子节点:第三层为叶子节点,每个叶子节点页可存储 16 条...
回答重点
Delete 用于删除行数据,但保留表结构和相关的对象。
Drop 用于完全删除数据库表,包括数据和结构。
Truncate 只删除数据,不会删除表结构和索引等其他结构。
从性能来看,Drop > Truncate > Delete
扩展知识Delete本质上这个删除其实就是给数据行打个标记,并不实时删除,因此 delete 之后,空间的大小不会变化。
而且 del...
回答重点MySQL 事务的二阶段提交是指在 MySQL 中,为了确保redo log(重做日志)和 binlog(二进制日志)之间的一致性,使用的一种机制。MySQL 通过二阶段提交来保证在crash recovery(崩溃恢复)时,不会出现数据丢失或数据不一致的情况。
二阶段提交的两个阶段:
准备阶段(Prepare Phase):在事务提交时,MySQL 的 InnoDB 引擎会先写入...
回答重点设计表的时候,在满足业务需求的情况下,需要额外考虑表结构的高效性、扩展性以及维护性。
1)选择合适的数据类型:为字段选择合适的数据类型可以有效减少存储空间,并提高查询效率。例如:
使用 INT 而不是 BIGINT,前提是如果数据不会超出 INT 范围。
使用 VARCHAR 而不是 TEXT,如果字段长度比较短且可变。
使用 DATE、DATETIME 或 TIMESTAMP 而...
回答重点
题目信息不足,那就顺着不足的信息直接回答,不要强加 CPU 核数、I/O密集、CPU 密集等概念限制自己的思考,在直接回答答案后再提出这些概念即可。(还有一种方式就是继续和面试官沟通追问,具象化题目再回答)
分析题目的意思:每个任务需要花费的时间是 0.1s,线程池要在 1s 内处理完这 1000 个任务,问线程池的参数该如何设置。
一个任务需要花费 0.1s,即一个线...
回答重点根据官方回应出现 bug 的原因是运营人员配置错营销模板导致的,即优惠额度和优惠类型都写错了。
实际上,类似的人为错误是难以完全避免的。作为开发人员,我们可以从产品和技术的角度出发,思考如何尽量降低人为失误的发生几率,并通过及时的预警、拦截等机制,在出错后减少资损。
从产品侧思考很多敏感场景我们需要“防呆设计”,例如用户需要输入日期这个场景,程序通过日期格式验证(如:YYYY-M...
回答重点
题干没有告知峰值的统计单位,可以直接询问面试官,原理都是一样的。本答案以秒作为单位,统计每秒的最大值。
我们要统计每秒钟内的最大并发流量,也就是在某一秒内有多少个事件处于活动状态(即时间段的重叠),可以使用差分数组和扫描线思想来实现。
我们可以通过将每个事件活动的开始时间和结束时间记录为增量(开始时流量 +1,结束时流量 -1),并通过扫描线的方式对每一秒进行累加,最终得到每秒的...
回答重点
接口变慢的原因可能非常复杂,涉及到 硬件资源、网络、应用程序代码、数据库 等各个层面。
接口变慢的排查思路
大部分情况下,接口变慢的排查思路按照以下的几点来回答面试官(注意,不要过度发散)
利用服务的监控(目前大部分公司项目都部署在云服务平台上,都会提供基础的监控大屏),或使用监控工具(如 Prometheus + Grafana、Zabbix等)查看系统的 CPU、内存、磁盘...
回答重点线上 CPU 飙高是一个比较常见的问题,并且它的排查手段比较流程化,非常适合套在各个项目中,大家按照我下面的思路简单加点细节就可以使用在自己的项目上了。
1)首先确认哪个进程占用 CPU 过高,登录服务器利用 top 命令查看。
top 命令是 Linux 下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于 Windows 的任务管理器
2)确认 CPU 利用率很...
回答重点利用 jstat 监控和分析 JVM 内部的垃圾回收、内存等运行状态。可以用它来查看堆内存、非堆内存等的实时状态。
可以使用 jmap 查看, JVM 堆的详细信息(包括堆的配置、内存使用情况、GC 活动等)。
在发生 OOM 时,可以根据 jmap 得到堆转储文件(建议增加JVM启动参数,-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpP...
回答重点遇到线上问题,第一时间是止损,如果发现 Redis 内存溢出,则应该立即扩容,增加 Redis 实例的内存,保证线上业务正常运行。
然后再排查内存溢出的可能原因:
数据过多: Redis 中存储的数据量过大,超过了可用内存。
数据过期策略失效: 大量的 key 没有设置过期时间,导致内存不断增长。
大对象或大数据结构: 某些 key 关联的数据结构(如 hash、list...
重点回答1)使用无锁数据结构:可以使用无锁的并发队列,如Java的ConcurrentLinkedQueue,它采用了非阻塞算法,避免了加锁的开销。这样,多个生产者可以并发地将消息添加到队列中,而消费者可以从队列中安全地读取消息。
2)批量操作:生产者可以批量发送消息,减少锁竞争的频率。例如,一个生产者可以先在本地缓存一批消息,然后一次性将这些消息推送到队列中。这减少了多次加锁解锁的开销。
...
回答重点可以使用 MySQL 或 MongoDB 的空间索引,或者使用 Redis 提供的 Geo 数据结构来存储商户位置的位置信息来实现根据距离的快速查找。
使用空间索引例如 R-tree,它适用于二维空间的树形数据结构,能够高效地进行范围查询和最近邻查询。将商户位置(经纬度)数据按照地理区域组织成树结构,可以快速找到位于用户当前位置附近。
像 MySQL 就支持 R-tree,或者使用 ...
重点回答这个问题虽然主要考察对操作系统缓存、文件系统和磁盘的理解,不过最好在开头再提一下 Java 中的操作,表现出从应用层到底层 DMA 的全方位理解。
第一步:写入文件缓冲区为了提高效率,写入文件都会利用缓冲区,即当写入数据时,数据先被存储到缓冲区,而不是直接写入磁盘。缓冲区的目的是减少磁盘 IO 操作的次数,提高性能。
一般用的是 BufferedOutputStream 或 Buf...
回答重点1)首先需要排查并确定根因通过监控工具(如Prometheus、Grafana等或云上自带的一些监控)查看 Redis 的 CPU、内存、命令执行时间或带宽等指标,确定瓶颈所在。
2)依据根因针对性解决问题如果是内存耗尽,可能需要增加机器的内存量(升配),即临时升配解决线上问题后。
后续再走查代码和了解相关业务,判断有些数据是否有必要都存储到 Redis 中,有些数据的过期时间是...
回答重点1)先定位慢在哪儿?需要定位导出 excel 慢在哪里:
业务逻辑慢?
数据库查询慢?
excel 生成慢?
2)针对性解决慢的问题如果是业务逻辑处理很慢,则需要优化调整逻辑,比如将一些在循环内的多次 RPC 调用,变成一次(或更少)的批量 RPC 调用。
如果是数据库查询慢,则查看 SQL 是都命中索引,是否有额外的排序逻辑等等。
一般情况下导出的场景都会分页查询数据库,可以将...
回答重点对于百万数据的导入,一般需要关注三类问题:
1)内存,如果一次性在堆内加载过多的数据,可能会导致内存溢出。2)时间,百万数据插入数据库需要一定的时间,同步调用可能会使得方法超时。3)异常,百万数据中可能会有很多异常的情况,比如格式错误、重复数据等等。
内存是有限的,不能一次性将 excel 内的所有数据都加载到内存中,需要分批加载。
像 apache poi 会将整个文件加载到内存中...
回答重点微信和支付宝都会支付成功,因为支付渠道是第三方系统,它们之间的数据是不相通的,因此无法阻止用户付款。
这样一来同一笔订单,用户就会多付了一笔钱,如何避免这个情况?
思路其实很清晰,不管是支付宝支付还是微信支付,用户支付后三方都会进行回调,这个回调处理逻辑在我们的系统中,因此我们可以在这里控制。
支付单都会有状态机,例如从支付中到支付成功,比如 update pay_info s...
回答重点这种情况在正常的业务场景中是有可能出现的,因为订单都会有定时取消的逻辑,比如 10 分钟或者 15分钟,而用户刚好卡在这个时间点进行付款,此时就会出现两种情况:
1)用户支付成功,支付回调的那一刻支付单刚好还没取消,而等回调结束,取消支付单的事务提交,支付单取消。此时用户扣款了,但是对应的权益或资产没了。
2)用户支付成功,支付回调的那一刻支付单已经被取消。但此时用户已经扣款,东...
回答重点如果刚好触发扩容,那么当前用户请求会被阻塞,因为 HashMap 的底层是基于数组+链表(红黑树)来实现的,一旦它发生扩容,就需要新增一个比之前大 2 倍的数组,然后将元素搬运到新的数组上。
而 1G 的 HashMap 够大,所以扩容需要一定的时间,而扩容使用的又是当前的线程,所以用户此时会被阻塞,等待扩容完毕。
如何改造现有 HashMap 结构而优化处理这种场景?此时可以借鉴 ...
回答重点首先用户(客户端)的请求是先打到网关,再由网关请求各后端服务,因此需要确保客户端到网络连接的超时时间(通常是 HTTP 请求),需要大于网关调用后端服务(通常是 RPC 请求)的综合时间。
其中又有一些细节需要考虑:
1)网关调用几个服务的方式
网关调用后端需求可以是串行,也可以是并行,例如上面的图中的三个服务,假设请求服务 A 需要花费 1s、请求服务 B 花费 2s、请求服...