Bootstrap

Java实战经验分享

1. 项目优化与性能提升

面试问题:

聊聊你印象最深刻的项目,或者做了哪些优化

  1. 你在项目中如何解决缓存穿透问题? 缓存穿透是我们做缓存优化时最常遇到的问题,特别是当查询的对象在数据库中不存在时,缓存层和数据库都会被频繁访问,造成性能浪费。为了解决这个问题,我们通常会设置一个特殊的标记值(比如 -1),表示该数据在数据库中不存在。当下次查询时,如果缓存值是 -1,就直接返回,不会再次查询数据库。这种方式简单有效,避免了缓存每次都访问数据库的性能瓶颈

  2. 如何处理缓存击穿问题? 另一个常见的问题就是缓存击穿,通常发生在缓存中某个热点数据过期时,多个请求同时查询这个数据,导致大量请求直接访问数据库。为了解决这个问题,我们可以通过设置不同的缓存过期时间来避免多个缓存同时过期,此外,还可以使用加锁机制,保证只有一个请求能查询数据库,其他请求则直接等待缓存更新

项目中的优化:

在项目中,我们也使用了定时任务来定期刷新热点数据缓存,避免在高并发场景下,缓存过期导致大量数据库请求。此外,采用了缓存预热机制,提前将热点数据加载到缓存中,从而避免流量高峰期缓存不命中的问题

2. 分布式锁的使用

你们项目中是如何使用分布式锁的?能具体讲讲它的工作原理和实现吗?

  1. 分布式锁的工作原理是什么? 分布式锁是为了在分布式系统中保证多个节点对共享资源的访问排他性。它的工作原理是,通过某种机制,确保在同一时刻只有一个节点能够获得锁,其他节点会被阻塞直到锁被释放。常见的实现方式包括基于数据库的锁、Redis的SETNX命令、以及Redisson等高层封装

  2. 你们是如何实现锁的失效机制的? 为了防止死锁的发生,我们在分布式锁实现时,需要为锁设置超时时间。比如,在Redis中,我们可以使用SETNX命令来获取锁,锁设置一个失效时间,这样即使请求在执行过程中发生异常,锁也会在超时后自动释放,避免死锁问题

  3. Redisson的分布式锁能解决哪些问题? 在我们项目中,我们使用了Redisson来实现分布式锁,Redisson封装了Redis的各种操作,提供了更加稳定的分布式锁实现。而且它自带的watch dog机制,可以在锁的过期时间到达时自动续期,避免了锁过期导致的并发问题

  4. Zookeeper和Etcd是如何保证分布式锁的互斥性的? 对于Zookeeper,它通过使用有序节点和watch机制来保证分布式锁的互斥性。每当某个节点释放锁时,Zookeeper会通知下一个获取锁的节点。Etcd则是通过基于Raft协议的分布式一致性算法来保证数据一致性,结合Prefix机制和watch功能实现分布式锁

3. 分布式事务的解决方案

在分布式系统中,如何处理分布式事务?你在项目中用了什么方案?

  1. 你理解的CAP理论和BASE理论是什么? CAP理论描述了在分布式系统中,一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)三者不可兼得。而BASE理论则是关于分布式事务的一种解决思路,它强调的是“基本可用、软状态、最终一致性”,并不是像传统的ACID那样强一致性

  2. 你在项目中使用了什么分布式事务解决方案? 在我们项目中,我们使用了TCC(Try、Confirm、Cancel)方案来解决分布式事务的问题。TCC方案的核心思想是:对于每个操作,都需要定义Try、Confirm和Cancel三个阶段。Try阶段执行操作的预处理,Confirm阶段进行提交,Cancel阶段则在失败时回滚之前的操作。TCC方案能够帮助我们处理不同微服务之间的数据一致性,并且通过补偿机制保证最终一致性

  3. Seata的使用场景是什么? Seata是一个分布式事务解决方案,能够帮助我们在微服务架构中处理跨服务的数据一致性。它通过全局事务管理器协调多个本地事务,确保事务的一致性。在我们的项目中,Seata解决了微服务之间的分布式事务问题,尤其是在大规模并发场景下,能够有效减少事务回滚和数据不一致的风险

  4. 你们如何保证接口的幂等性? 接口的幂等性是分布式系统中一个非常重要的设计点,特别是在面对网络问题或请求超时时。我们通过多个策略来确保接口的幂等性:例如,在数据库中设置唯一约束来避免重复插入,或者在操作时生成唯一的请求ID,确保相同的请求不会被执行多次

关于接口的幂等性:

我们在接口设计时通常会使用select + insert + 主键冲突的方式来确保接口的幂等性。如果接口请求已经被处理过,数据库的主键/唯一索引冲突就会自动返回已经处理的结果。除此之外,我们还使用了token令牌、乐观锁等方式来保证在高并发场景下接口的幂等性,避免重复提交订单或多次扣款的情况

4. MySQL架构设计

面试问题:

你们的MySQL架构是怎样的?能介绍一下如何保证数据库的高可用性吗?

  1. 你们使用了什么样的数据库架构? 我们公司在数据库架构上采用了主从复制的方式,即一主多从。主库负责写操作,从库负责读操作,这样可以有效分担主库的读压力,提升系统的并发能力。每个从库都会定期同步主库的数据,这样即使主库宕机,从库也能保证数据的完整性

  2. 如何处理MySQL的高可用性? 为了保证MySQL的高可用性,我们使用了MHA(Master High Availability)方案,当主库发生故障时,能够自动切换到从库,确保业务不中断。此外,我们还会使用数据库中间件(如Mycat)来对数据库进行分片,以应对海量数据的高并发需求

  3. MariaDB多主集群方案的优缺点是什么? MariaDB的多主集群方案通过Galera Replication实现多主节点之间的数据同步,能够同时支持多个节点进行读写操作,提升了系统的可用性和扩展性。缺点是,当某个节点变慢时,其他节点的性能也会受到影响,因此需要根据业务场景选择合适的数据库架构

  4. 数据库中间件的使用场景是什么? 我们在面对高并发、高数据量的需求时,使用了数据库中间件(如Mycat)进行数据分片。数据库中间件能够根据特定的规则将数据分散到多个数据库实例中,从而减轻单一数据库的压力,确保系统的高可用性和扩展性

日常工作中你是怎么优化 SQL 的?

MySQL 的性能优化可以分为 4 大部分
  1. 硬件和操作系统层面的优化
  2. 架构设计层面的优化
  3. MySQL 程序配置优化
  4. SQL 优化

  1. 硬件及操作系统层面优化
    从硬件层面来说,影响 Mysql 性能的因素有,CPU、可用内存大小、磁盘读写速度、网络带宽
    从操作系统层面来说,应用文件句柄数、操作系统网络的配置都会影响到 Mysql 性能。
    这部分的优化一般由 DBA 或者运维工程师去完成。
    在硬件基础资源的优化中,我们重点应该关注服务本身承载的体量,然后提出合理的指标要求,避免出
    现资源浪费!
  2. 架构设计层面的优化
    MySQL 是一个磁盘 IO 访问量非常频繁的关系型数据库 在高并发和高性能的场景中.MySQL 数据库必然会承受巨大的并发压力,而此时,我们的优化方式可以 分为几个部分 MySQL 程序配置优化 MySQL 是一个经过互联网大厂验证过的生产级别的成熟数据库,对于 Mysql 数据库本身的优化,一般 是通过 Mysql 中的配置文件 my.cnf 来完成的,比如: Mysql5.7 版本默认的最大连接数是 151 个,这个值可以在 my.cnf 中修改。 binlog 日志,默认是不开启 缓存池 bufferpoll 的默认大小配置等。 由于这些配置一般都和用户安装的硬件环境以及使用场景有关系,因此这些配置官方只会提供一个默认 值,具体情况还得由使用者来修改。
  3. SQL 优化又能分为三部曲
    慢 SQL 的定位和排查
    我们可以通过慢查询日志和慢查询日志分析工具得到有问题的 SQL 列表。
    执行计划分析
    针对慢 SQL,我们可以使用关键字 explain 来查看当前 sql 的执行计划.可以重点关注 type key rows
    filterd 等字段 ,从而定位该 SQL 执行慢的根本原因。再有的放矢地进行优化
    使用 show profile 工具
    Show Profile 是 MySQL 提供的可以用来分析当前会话中,SQL 语句资源消耗情况的工具,可用于 SQL
    调优的测量。在当前会话中.默认情况下处于 show profile 是关闭状态,打开之后保存最近 15 次的运
    行结果
    针对运行慢的 SQL,通过 profile 工具进行详细分析.可以得到 SQL 执行过程中所有的资源开销情况.
    如 IO 开销,CPU 开销,内存开销等
;