java基础

69 阅读8分钟

jvm

java元空间主要存储什么内容 元空间是放在直接内存。

  • java类加载信息。
  • 运行时常量池。 存储类的常量信息,包括字面量(如字符串、数字常量)和符号引用(如类和接口的全限定名、字段和方法的名称及描述符等)。这些常量在类加载时从.class 文件的常量池加载而来,并在运行时解析为直接引用。
  • JIT代码缓存。
  • java类的元数据信息。

java并发

JMM

java内存模型,java虚拟机规范定义的一个抽象模型,用来描述多线程环境下共享变量的内存可见性。 共享变量

线程池

threadLocal

阿里巴巴开源的 TransmittableThreadLocal(TTL) 是专门用来解决 线程池环境下父子线程之间 ThreadLocal 变量传递问题 的框架。- JDK 自带的 ThreadLocal:只能在本线程内使用,无法跨线程传递

  • InheritableThreadLocal:虽然支持父子线程传值,但只在线程创建时生效,对线程池复用的线程无效

ArrayBlockQueue 阻塞队列

数组实现单ReentrantLock+二个conditon条件。 LinkedBlockingQueue 链表,二个ReentrantLock.

Mysql

查询优化

小表驱动大表原则。

子查询优化(子查询会用到临时表,尽量避免,使用效率更高的join来优化)

insert优化:•批量插入•文本装载方式,从本文装入数据,比insert语句块20倍。

说一下事务的执行流程,具体用了哪些日志,什么情况下使用

执行事务,首先从buffer pool找到这条记录,没有从磁盘加载,生成undo log,修改内存页 buffer pool,不会立即写入磁盘,被修改的页标记为脏页,生成redo log,wal机制,但是做了优化,不会先写日志,也会先写到redo log buffer,

执行事务的时候,redo log从redolog buffer刷盘,涉及到一个二阶段提交,redo log进行prepare状态,写入binlog,接收到binlog写成功的信号,redo log标记为comit状态

binlog

binlog有三种主要的格式,分别是Statement、Row和Mixed。

Statement格式:这是最古老的格式,它记录的是原始的SQL语句。优点是日志文件非常小,能节省大量的磁盘空间和网络I/O。但缺点也很致命,有些SQL语句在主库和从库上执行的结果可能不一致,比如包含UUID()、NOW()这类函数的语句,容易导致主从数据漂移。

• Row格式:它不记录SQL,而是记录每一行数据被修改前后的具体内容。优点是复制非常精确,绝对不会出错。缺点就是日志量会变得很大,特别是当一条UPDATE语句更新了几百万行数据时,binlog文件会急剧膨胀。

• Mixed格式:这是目前MySQL默认使用的格式,它结合了上面两者的优点。MySQL会自动判断,对于绝大多数安全的、确定性的SQL,它会使用Statement格式来记录;而对于那些可能导致主从不一致的“危险”SQL,它会自动切换成Row格式来记录。可以说是一种非常智能和平衡的选择

redolog

redo log的写入过程并不是一步到位的,它涉及了几个层级。 首先,当有数据修改时,日志记录会先被写入内存中的一块专属区域,叫做 redo log buffer。 然后,这些在内存 buffer 里的日志,会在某个时机被写入到操作系统的文件系统缓存(OS Buffer)中。 最后,再通过操作系统调用 fsync(),才将日志从文件系统缓存真正地持久化到磁盘上的 redo log file 里。 这个从 redo log buffer 刷到磁盘文件的时机,可以通过参数 innodb_flush_log_at_trx_commit 来精确控制,这也是一个面试时经常被问到的点。它有三种策略:

• 设置为 1(默认值):最安全,也最符合ACID的要求。每次事务提交,都会强制把redo log从内存同步刷到磁盘,确保数据万无一失。

• 设置为 0:性能最好,但最不安全。事务提交时,日志只留在内存的 redo log buffer 里,由一个后台线程大概每秒刷一次盘。如果服务器掉电,会丢失最近一秒的事务数据。

• 设置为 2:一个折中方案。事务提交时,日志会写入到操作系统的文件缓存,但不会立刻 fsync。如果只是MySQL进程挂了,操作系统没问题,数据不会丢。但如果整个服务器宕机,那文件缓存里的数据就没了。

mysql缓存区何时刷新到磁盘

MySQL缓冲区刷新到磁盘的主要时机:

  1. 数据页(Buffer Pool) :后台线程定期刷新、缓冲池空间不足、检查点触发、数据库正常关闭
  2. 日志(Log Buffer) :由innodb_flush_log_at_trx_commit参数控制,1=每次事务提交,2=每秒刷新,0=每秒刷新
  3. 双写缓冲(Doublewrite Buffer) :在数据页刷新前写入,作为数据完整性保障
  4. 写缓冲(Change Buffer) :后台线程空闲时、缓冲池空间不足、数据库关闭、redo log写满

对于生产环境,建议将innodb_flush_log_at_trx_commit设置为1(默认值),以确保数据的持久性和一致性,虽然这会略微降低写入性能。而Buffer Pool的大小应根据服务器内存合理配置(通常为物理内存的50%-75%),以提高查询性能。 Change Buffer用于优化非唯一索引的写入操作:

分页查询优化

游标分页适合 “向前/向后浏览” 的流式数据场景,不适合 “随机跳页” 的页面浏览场景。

分页方式SQL 示例性能特征
OFFSET 分页LIMIT 10 OFFSET 100000先扫描前 100000 行再丢弃,性能线性下降
游标分页WHERE id < ? LIMIT 10直接利用索引定位,性能恒定 O(pageSize)

MQ

RockeMq原理

  • NameServer 用于服务发现,几乎无状态节点,可以集群部署,节点之间没有任何信息同步。内部维护topci和broker对应关系,并且和所有的broker保存心跳连接,在prodcue和consume发布或者消费消息,向所有的namsServer发出获取连接的broekr信息,每个直接都是独立的。
  • broker 负责消息中转,主要职责是存储,转发消息。 分为master,slvae。每个broker和nameservier的所有节点建立长连接,定时30s注册topic消息到nameSErve。namSErver定时10s,扫描所有存活broker上的连接,如果超过2分中国

mq消费如何确保消息不丢失

  • 生产端 kafak三种消费语义,(ack=0,1,-1) 0代表发送不就管了,最多一次,1,最少一次,要等到leader副本确认。-1是不仅仅是leader副本,也需要follow副本,消息的可靠性最高。 使用最高的ack。并且同步发送,生产端要重试。
  • broker端 开启同步刷盘
  • 消费端 消费要手动提交位移,消费 异常要进行记录,消费要重试。

Kafak重平衡,重启服务如何保证kafka不发生重平衡,有什么方案

对于关键的消费者服务,静态成员(Static Membership) 是最有效和推荐的解决方案,它可以让消费者在短时间内重启后,带着相同的身份重新加入消费组,从而避免触发完整的重平衡

特性LEO (Log End Offset)高水位 (High Watermark, HW)

表示意义日志中下一条待写入消息的 Offset。所有同步副本都已复制完成的最新消息的 Offset。 更新者每个副本(Leader/Follower)独立更新。Leader 根据所有 ISR 的 LEO 最小值来更新。 作用标记已接收消息的末端。标记消息对 Consumer 的可见性和持久性。 关系HW≤LEO:HW 总是小于或等于 LEO。一致性:HW 保证了所有副本在 HW 之前的消息是相同的。

Redis

redis pipLine和事务的区别

pipLine 是将多个命令一次性发送给服务器,减少网络往返次数,不保证原子性,高吞吐,适合批量操作。 事务:弱原子性。执行失败,后面命令依然会执行,不会回滚。适合非关键业务,天然隔离,单线程。无直接持久化,依赖AOF、RDB。

过期删除策略

redis实际是 选择惰性删除+定期删除二种策略来搭配使用。 定期删除 每次间隔一段时间,从数据库取出一定数量的key,来检查,过期就删除 定时删除: 设置key的时候,设置一个定时任务,时间到期就删除,对cpu压力比较大。

惰性删除:不主动删除key,每次数据库访问key,检查key是否到期。

数据淘汰策略

  • volatile-randonm

  • volatile-LRU

  • volatile-ttl

  • volatile-LFU

  • allkeys-lru

  • allkeys-random

  • allkeys-lfu

Reids集群如何实现数据同步

完全同步

  • 初次同步:一个slave首次连接到主服务器。
  • slavae数据丢失
  • 主服务器数据发生变化。 主要是通过rdb文件来完全同步

增量同步

是基于PSYNC命令,

gossip协议在redis中实现了什么作用

Redis Cluster使用Gossip协议实现节点间的状态同步和一致性维护。Gossip协议是一种去中心化的通信机制,通过节点间的"谣言传播"方式交换信息,具有高容错性和扩展性。下面详细说明Redis中Gossip协议的具体应用:

  1. 状态同步:确保每个节点了解集群中所有节点的状态(如在线、槽分配)
  2. 故障检测:通过心跳检测发现节点失败,触发故障转移
  3. 去中心化:无需主控节点,适应动态集群变化