面试经验合集|社招三年菜鸡面试经历
大厂面试指北

catelog

  • java
    • 基础
      • 权限修饰符和区别 , default效果
      • 异常体系
      • 类反射获取类实例方式
      • 类锁和实例锁区别
    • 集合:
      • 时间复杂度
      • ArrayList
        • ArrayList扩容时容量变为原来的多少倍?
        • 数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用 Array 而不是
        • 遍历删除使用list的iterator
      • LinkedList
        • 底层是由什么实现的?
        • 如何提高LinkedList的查询效率
      • HashTable
        • 为什么扩容 2n +1 ,
      • HasMap
        • 计算 tab下标方式 , 原因
        • 为什么是2的n次幂
        • 是否需要rehash
        • 转为tree为什么是8
        • 1.7链表环怎样造成的 , 1.8怎么解决
      • currentHashMap
        • hm和chm 和table区别
        • 为什么不允许null值
      • linkedhashMap
    • 多线程
      • thread的start和run区别 , start可以调用多次吗?
      • 单例模式
      • volatile(内存屏障,嗅探机制)
      • 开启多线程方式
      • wait ,locksupport.park , sleep区别
      • 任务能否终止
      • 线程顺序保证
      • 线程通信
      • 线程池
        • 如何销毁空闲线程
      • threadlocal(原理,内存溢出)
      • blockingqueue
      • 随机数原理
      • happens-before
      • sync关键字原理
      • 对象:
      • 偏向锁
      • 轻量锁
      • 重量锁
      • 锁降级
      • aqs
      • aqs,队列中的线程怎么唤醒的?
      • synchronized锁与ReentrantLock锁的区别?
      • 结合aqs 说说ReentrantLock
        • ReentrantLock的条件等待队列?
      • 其他aqs实现锁中怎样实现自身功能的
      • ABA问题怎么解决?
      • 读写分离锁
      • 锁粗化
      • unsafe
    • jvm:
      • 内存划分 - 运行时分区
      • 对象内存分配
      • 类加载
      • 双亲委派 ,如何打破
        • 类加载过程
        • Tomcat为什么要重写类加载器
      • gc
        • 强弱软虚引用
        • 垃圾算法
        • 分代算法
        • 如何确定一个对象可以被回收
        • 垃圾回收器
          • G1 :
        • 三色标记法 , 标记清除 , 引用计数法 区别
      • jvm参数
      • dump
      • gc日志
      • 容器和jvm堆内存限制
      • 排查方式
        • top 进程 , 找到线程 , 查看线程占最高cpu
        • jstat / jmap -heap 堆使用情况
        • jstack 线程 , 死锁
        • jvisualvm
  • mysql:
    • undolog(回滚日志)
    • redolog(重做日志 事务两步提交)
    • bufferpool
    • 事物特性
    • 事务隔离级别
    • mvcc
    • 全局锁
    • 表锁
      • 自增锁
      • 意向锁
    • innodb锁
      • 记录锁
      • 间隙锁
      • next-key 临键锁
    • B+ tree 和 b tree 区别
    • 为什么不用红黑树
    • 索引优化
    • 聚簇索引 非聚簇索引
    • 联合索引
    • 索引失效
    • 索引覆盖 / 下推
    • 页的预读机制
    • bufferPool
    • readview
    • 行锁升级为表锁
    • innodb 和 myisam区别
    • 分库分表
    • 主从复制
      • binlog 格式
    • 死锁
    • 查询缓存
    • 调优
      • explain
      • join
      • exist in
    • binlog 维护
    • 深分页
    • 什么场景会产生数据库死锁,怎样处理
    • 唯一索引是否可以插入一条空
    • 表创建后生成什么文件?
    • 聚簇索引怎样存储大文本 , 怎样优化?
    • sql
    • group having , oder by执行顺序
  • spring
    • filter和intercepter区别
    • sevelet生命周期
    • spring怎样实现的依赖注入?ioc的单例对象被使用时怎样实现的线程安全?
    • springaop
    • springioc
      • beanfactory / factoryBean
      • bean生命周期
    • 解决循环依赖
    • springboot启动流程
      • 自定义runner
  • redis:
    • redis工作模型
    • 过期策略
    • 性能高原因
    • linux io模型
    • 阻塞 , 同步
    • bio , nio , aio区别
    • 缓存失效
    • 如何保证缓存一致性
    • redis数据结构
      • string
        • 和java String区别
      • hash
      • list
      • set
      • zset
      • mysql不使用跳表 , 平衡二叉树原因
    • 持久化
      • rdb
      • aof
        • aof重写
      • 混合
      • 容灾策略
    • 高可用
      • 主从机制
      • 哨兵
      • 集群
        • 一致性
    • pipeline
    • redis分布式锁
      • lua脚本命令是什么
    • bigkey
    • 布隆过滤器
    • hashes分桶
    • Hyperloglog 计算uv
  • 系统设计
    • 分布式id生成
    • 大文件上传
    • 分布式事务
      • 2pc
      • 3pc
      • tcc
    • 分库分表动态扩容?
    • 并发抢票
    • 下单后八小时未支付,发一条消息提醒用户支付
    • 接口幂等性处理
    • 发送消息时发送失败如何处理
    • 如何实现秒杀业务?有用到分布式事务吗,如何实现
    • 本地缓存提高qps
    • 业务
  • 其他
    • http 和rpc区别
  • 算法:
  • rocketMq
    • 高性能
    • 数据同步方式
  • es
    • solr和es的区别
    • es的深分页会有什么问题?
    • es 两个集群 , 怎么并发保证一致性
    • profile优化
    • 部署
  • kafka(待补充)
    • 基本概念
    • key的分发
    • 分区分段+索引
    • ack
    • 防止生产者数据丢失
    • 幂等性
    • 事务性
    • 顺序写和零拷贝
    • consumer rebalance
    • 避免重复消费
    • zookeeper的作用
  • springcloud
    • feign重试策略
    • 网关用的什么,gateway和zuul的区别
    • springcloud用了哪些组件
    • nacos的通讯协议
    • 服务雪崩概念
    • 限流、熔断介绍
  • flink
    • flink集群部署
  • hbase
  • hadoop
  • doris
  • 未整理

java

基础

权限修饰符和区别 , default效果

只允许在同一个包中的进行访问

异常体系

类反射获取类实例方式

类锁和实例锁区别

静态static修饰的sync为类所 , 其他的均为对象锁 , 包括sync(this)

集合:

时间复杂度

o(1), o(n), o(logn), o(nlogn)
时间复杂度与空间复杂度-o(1)、o(n)、o(logn)、o(nlogn)、斐波那契
o1 数组 , 常数
On 遍历 , 耗时1 :1
O logn 二分查找 ,各种tree , 线性增长,
O nlogn 归并排序 ,
O n^2 冒泡排序

ArrayList

ArrayList

ArrayList扩容时容量变为原来的多少倍?

size+ (size>>1) , 1.5

数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用 Array 而不是

ArrayList?
Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类型

遍历删除使用list的iterator

LinkedList

linkedlist详解

底层是由什么实现的?

双向链表

如何提高LinkedList的查询效率

迭代器遍历提高效率
linkedHashMap , 双向链表 + hash , 避免了链表在遍历查询上的耗时 ;
zset , 给链表增加索引层
zset如何解决内部链表查找效率低下

HashTable

为什么扩容 2n +1 ,

素数取模tablelength更加下标更平均

HasMap

计算 tab下标方式 , 原因

static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
tab[i = (n - 1) & hash]

HashMap中hash(Object key)原理,为什么(hashcode >>> 16)
使用高位与低位进行位异或 , 使用位与 或者 位或 要么都为 0 要么都为1 ,只有位异或让 1 和0 的结果平均
java位运算

为什么是2的n次幂

hashtable中使用hash% length , 在length为2次幂时 , hash%length=hash&(length-1) , 计算机处理 位与 操作更快

是否需要rehash

1.8不需要 , length始终为2次幂时 , hash %(原长度-1) 与 hash %(2* 原长度-1) 区别在于, hash&原长度是否为0 , 为0 新坐标是原坐标位置不变 , 不为 的新坐标是原坐标+ 原长度,

 do {next = e.next;if ((e.hash & oldCap) == 0) { // hash&原长度是否为0if (loTail == null)loHead = e;elseloTail.next = e;loTail = e;}else {if (hiTail == null)hiHead = e;elsehiTail.next = e;hiTail = e;}} while ((e = next) != null);if (loTail != null) {loTail.next = null;newTab[j] = loHead;//为0 新坐标是原坐标位置不变}if (hiTail != null) {hiTail.next = null;newTab[j + oldCap] = hiHead; // 不为 的新坐标是原坐标+ 原长度,}

转为tree为什么是8

在8以前, 链表比tree快 , 链表遍历搜索时 , 时间复杂度为 链表length/n , tree的时间复杂度log n,

1.7链表环怎样造成的 , 1.8怎么解决

1.7多线程扩容时 , 因为是遍历迁移至新tab , 会造成链表收尾互相引用
1.8 是遍历先放入临时链表 , 在迁移 , 类似原子行操作
hashmap不能在多线程使用

currentHashMap

hm和chm 和table区别

为什么不允许null值

chm和table在多线程时 , 无法保证get和contains的操作原子性 , 所以无法判断是key为null ,还是key对应的value是null ;
hashmap不能在多线程使用 , 所以允许

linkedhashMap

聚合hashmap , 重写了putval中post方法 , 对每个插入的元素与前一个元素进行了绑定
实现 lru , lfu , 通过accessOrder标识指定插入的元素是否通过访问/ 插入顺序排序,
底层用的hashmap , 线程不安全 ;

多线程

系统 进程 线程 , 线程共享 , 进程通信 ,
进程有独立的内存地址空间 , 创建销毁需要回收资源
虚拟内存 , 置换磁盘数据页到内存中
JAVA 拾遗 — CPU Cache 与缓存行
系统的线程状态和java的线程状态不同 , java的运行和就绪为一个状态runnable

thread的start和run区别 , start可以调用多次吗?

start 创建线程就绪状态 底层native方法
run是runnable的子类实现 ,真正执行
不能多次调用 , start执行时判断线程状态 , 如果不是new 就是抛异常了

单例模式

volatile + 双校验 实现单例模式
反序列化导致单例失效 , 重写readResolve , 返回已存在的实例 ;
枚举防止反序列化

volatile(内存屏障,嗅探机制)

内存屏障
使用汇编的lock命令 , 禁止指令重排;
线程对一个volatile修饰的变量进行写操作, 会让该缓存行通过cpu总线回写到系统主内存 , 其他cpu会嗅探到cpu总线上传输的数据 , 让自己缓存行中的变量引用失效 , 下次其他cpu必须从内存中重新读取该变量的引用到缓存 ;
一写多度 , 读写锁 , 多线程读标示位;

开启多线程方式

thread.start , runnable , callable , callabletask
callable怎样实现从其他线程中获取结果 , 其他任务执行完就会通知主线程 还是 主线程主动去查看子线程状态?

wait ,locksupport.park , sleep区别

locksupport使用 二院信号量 , 可以前置获取 , 表示获取到锁 , 所以可以先unpark 再 park

wait必须在以该对象为锁的同步代码块中

package com.example.thread;import java.io.IOException;public class ObjectLocktest implements Runnable {private Object obj;public ObjectLocktest(Object obj) {this.obj = obj;}public static void main(String[] args) throws IOException {Object obj = new Object();ObjectLocktest locktest = new ObjectLocktest(obj);locktest.run();System.in.read();}@Overridepublic void run() {new Thread(() -> {synchronized (obj){
//            synchronized (this){//这样就会报illlegalException,必须用obj作为锁才能在同步代码块中使用objtry {System.out.println("11111");obj.wait();} catch (Exception e) {e.printStackTrace();}}}).start();}
}

任务能否终止

cancel() , 线程外对该线程设置中断标识 , 该线程自旋判断是否设置了标识 , 然后cancel自己 ;
stop已经过时;

线程顺序保证

join ;
wait ,notify ;
condition的await 和 singal;
线程池 ,

线程通信

sync锁
wait , notify : 对象的monitor锁 , 有同步和 等待队列 , wait()后的线程进入等待队列 , notify后进入同步队列 , 等待cpu调度
线程池;
pipeline;

线程池

参数含义 , 核心 -> 队列 ->最大线程
各种队列
拒绝策略
根据指标动态调整线程池参数

如何销毁空闲线程

如何销毁空闲线程
workqueue会阻塞获取线程任务 , 如果超时 ,就会销毁 , 超时内部是用的aqs的await , 底层用的locksupport

threadlocal(原理,内存溢出)

当前线程为 key
entry 弱引用 , 释放threadlocal 和 threadlocalMap ;
手动remove , 释放线程与threadlocal ;
put时也会遍历entry , 清理key为null的遗留entry

blockingqueue

队列类型 和 特征
ArrayBlockingQueue 定长数组 ,
linkedBlockingqueue 未指定长度情况下可能会有内存溢出 ;
DelayQueue 指定时间才能被消费;
PriorityBlockingQueue 无界队列
SynchronousQueue 同步 , 可选公平和非公平 , 非公平消费者和生产者绑定后 , 新来的消费者生产者可能一直没有对应方去处理;

随机数原理

使用ThreadRandom 根据线程生成的seed 产生的随机数 , 比Math.Random产生的更加随机

happens-before

定义了java多线程的规则 , 保证可见性 和 顺序性

锁升级过程

sync关键字原理

方法上 和 同步块 , monitor in exit

对象:

对象头中的monitor markWord gc标记 hash信息 属于哪个类的实例 数组对象数组还会记录长度

偏向锁

线程获取锁时如果没有线程id(为偏向状态) ,使用cas将锁对象的对象头信息中放入自己的线程id , 标识自己占有锁 , 如果失败查看占有锁线程栈中lockrecord的标识是否为null , 如果不为null, 表示线程仍持有锁 , 就会升级成轻量锁 , 成功后再次获取锁 时只会判断线程id是否还是自己

解锁: 持有锁的线程只会将自身线程的栈中的最近一条 lockrecord的 obj字段设置为null

轻量锁

重量锁使用会进行用户态和内核态切换 , 造成线程阻塞, 在线程竞争不激烈时, 线程任务耗时较短时, 耗费资源 , 所以采用轻量锁 , 其他线程在获取不到锁时, 会进行自旋 , 而不是阻塞 ;
使用cas将栈信息复制到锁对象中进行占位 , 占位失败会进行适应性自旋 , 获取锁后更改之后自旋的次数的阈值 , 超过阈值后还是会进行阻塞
解锁 : cas替换对象头信息 , 如果此时锁被升级成重量锁 , 还要唤醒阻塞的线程

重量锁

对象的monitor实现 , waiting queue 和 entry queue 来存放请求锁线程, blocking queue存放wait阻塞的线程 , 仅有一个线程可以去竞争锁
重量锁会一开始就尝试获取锁1次, 增加吞吐量 , 因为阻塞线程的唤醒需要资源量大 ;

锁降级

gc时 , jvm检查闲置的monitor , 尝试降级

aqs

aqs
管理竞争公共资源的线程的框架 , 只要实现 try.acquire 获取锁 和 release释放锁 就可以 ,
有独占和共享两种模式 , 通过内部标识state控制,
内部有个链表队列 , 队列中每个node都封装了线程对象 , waitStatus描述了当前node所处的状态 , 是否被阻塞 ,是否等待唤醒 , 是否被取消;

aqs,队列中的线程怎么唤醒的?

release方法释放锁, 遍历等待队列, 拿到队首元素使用unpark唤醒

synchronized锁与ReentrantLock锁的区别?

ReentrantLock 可选非公平和公平 , 代码层面 , 可以指定唤醒某些阻塞的线程 ;
synchronized jvm层面 , 非公平锁 , 只能唤醒所有等待锁线程 , 重量锁情况下比ReentrantLock 性能低 ;

结合aqs 说说ReentrantLock

公平时加锁 , 先判断是否有线程持有锁 , 队列中是否有线程排队 ,再去自旋 ;
非公平一开始就尝试获取锁 , 失败后会再去获取锁, 再失败才会进队列 , 增加吞吐量 ;
如果已经持有锁 , state+1 , 表示重入 , 直到state 为0 时 , 其他线程才会获取到锁 ;

ReentrantLock的条件等待队列?

通过ReentrantLock获取一个condition对象 , 可以根据业务逻辑 ,使用signal()唤醒await()的线程 ;
condition中也有一个队列 , 不同于aqs的队列 , 这是一个单向的 , await()时将自己放入condition队列 , 当signal的时候会把condition队列中的线程取出放入aqs队列竞争锁;

其他aqs实现锁中怎样实现自身功能的

读写锁
readwriteLock 的读锁使用的aqs的共享锁 , 写锁是独占锁 , 通过判断state来确认当前锁是读锁还是写锁, , 获取读锁时判断是否有写锁 , 有就阻塞 , 不是写锁就记录当前线程的state , 是当前线程就 +1;

countdownlaunch , 共享锁, state减到0时, 唤醒主线程;

Semaphore, 共享锁 , state减为0时 , 线程阻塞 ,进入队列 ;

CyclicBarrier , 独占锁 , 与countdownlaunch相反 , 所有子线程串行执行, 到达await()锁处阻塞 , 所有子线程都执行到await()位置后 , 所有子线程才能继续; 可以设置超时 , 和到达屏障后进行的回调函数 ;

ABA问题怎么解决?

使用 原子时间/版本引用
atomicStamp/markReference

读写分离锁

乐观锁 , 适合读多写少场景

锁粗化

锁粗化 和 消除

juc(cas,unsafe,lockSupport)

unsafe

可以直接操作内存偏移量 ,跳过各种检查, 即使是阻塞的线程 , 导致无法被gc, 必须手动管理 , 所以不安全 ;
park ,unpark 通过调用linux的系统函数完成阻塞

jvm:

内存划分 - 运行时分区

线程私有: 虚拟机栈(每个方法产生一个栈帧进入虚拟机栈) , 本地方法栈(jni native方法) , 程序计数器(记录执行位置) ,
线程公有: 堆 (对象)1.8常量池和静态变量放到了Java堆, 方法区(类信息, 运行时常量池)1.8元空间为本地内存非jvm ,

对象内存分配

对象头 , 对象实际数据 , padding 必须补齐成8字节的倍数

类加载

bootstrap 加载器 ,扩展加载器, 应用加载器 , 自定义加载器

全面负责 , a类加载使用的classloader , a类引用依赖的类也将使用相同的classloader

双亲委派 ,如何打破

子classloader 优先让父类加载器进行加载 , 找不到在让子加载器加载
打破双亲委派 ,继承ClassLoader , 重写loadclass

类加载过程

当类被使用到时或者为启动类 会加载到内存 , 校验, 分配内存 , 初始化

Tomcat为什么要重写类加载器

Tomcat为什么要重写类加载器
实现jsp热部署
实现类隔离 , 不同加载器可以加载全限定类名相同的类

gc

基本只发生在堆内存 , 不回收各种连接

强弱软虚引用

强引用 , 不会被回收
弱 , 内存不够会被回收
软, 内存够不够都可能被回收
虚, 跟踪回收状态

垃圾算法

标记清除 , 标记后清除 , 老年代, 内存碎片
标记复制 , 内存只用一半 , 将未标记的复制到另一个半空间 , 内存浪费
标记整理 , 标记后移动对象 , 老年代 , 不产生内存碎片, 有利于新对象内存分配, 吞吐量大 , 延迟高

分代算法

对熬过不同垃圾回收次数的对象进行分类 ,
年轻代 eden 8:fromS1: toS 1 , 使用标记复制 , 每次使用eden和一块survive , eden空间不够时 , 进行gc , 将幸存的复制到另一块survive , 处理eden和旧的s;
默认15次后进入老年代 ;
动态年龄 , 某年龄的对象群体占的survive空间过大, 也会进入老年代,
老年代使用标记清除, 内存碎片高时用标记整理 , 大对象直接进入老年代 ,

eden空间不够时 , 发生在年轻代gc的叫 minorGc ;
老年代空间不够 , 将用fullgc对整个堆回收 ;

如何确定一个对象可以被回收

引用计数 , 0就可以回收;
可达性分析 , 静态常量等gcroot对象都引用不到的对象 可以被回收

垃圾回收器

serial 单线程回收器 ;
parallelNew 多线程收集器 , 标记 复制 ,年轻代 ;
cms , 并发收集 , 老年代 , 需配合parallelNew(why?) , 分为4个阶段 , 初始标记root引用的对象 , 并发标记(允许和用户线程一起执行) , 重新标记 , 并发清理(允许和用户线程一起执行) , 3色标记法和快照, 记录对象标记过程

G1 :

年轻代 和老年代同时为g1
不再有年轻代 , 老年代 , 将堆内存分成 region , 每个region可以转换成eden , old , survive , humongous(用来存放大对象)
分配对象策略 : 进行逃逸分析 , 如果只在方法内使用 , 只在方法栈上保存 , 空间不够 , 会进入eden , 线程私有的buffer , 最后进入humongous;
G1 Young GC , 将eden对象移动至survive , stw
G1 MixGC , eden 和 old , 过程是 标记 , 并发标记 , 最终标记 , 清除

三色标记法 , 标记清除 , 引用计数法 区别

jvm参数

xmn eden大小 , 一般设置为Xmx的2/8~3/8,等同于-XX:NewSize 和 -XX:MaxNewSize 。
old大小
初始堆内存
最大堆内存
gc回收器
jvm调优

dump

开启jvm参数 , oom自动dump ,手动dump 会 stw
dump 后 去easygc 在线分析堆栈

gc日志

容器和jvm堆内存限制

排查方式

top 进程 , 找到线程 , 查看线程占最高cpu

1.top展示进程
2.top展示cpu利用率高线程
3.转换成线程号
4.jstack 展示具体线程栈信息

jstat / jmap -heap 堆使用情况

jstack 线程 , 死锁

jvisualvm

mysql:

mysql视频教程

undolog实现事务 , redolog是wal方式保证刷盘时故障不丢失, binlog
sql经过应用层解析, 校验, 优化, 提交执行计划给存储引擎层

undolog(回滚日志)

用于事务回滚, mvcc, 故障恢复 , 生成一条与执行sql相反的sql日志 ;
事务提交后, 会把这条undolog放到待删除链表中 , 待小于当前事务的其他事务都提交后 , 才会删除 ;

redolog(重做日志 事务两步提交)

redo log buffer中记录, 之后刷盘到redolog中;
更改内存中数据页前先做记录,write ahead log , 用于故障后恢复 ;
主要配合写缓存 , 可以减少io次数 , 将随机io变为顺序io ;
事务提交时提交redolog到磁盘 , 持久化 ;
有不同的刷盘策略, 默认为每次事务提交前, 将变更记录到redolog buffer和内存页, 之后立即刷盘;
**二阶段提交 **
先写redo log , 再写binlog ,再改redolog状态为提交 , 相当于又开启了个事务 , 故障恢复时保证数据完整性 , binlog保证主从一致性

bufferpool

变更和读取缓存池, 之后统一刷盘
change buffer
数据页不再内存中时 , 将操作先记录在缓存池中 , 待之后统一刷到磁盘 , 减少io次数 ;

脏页
因为只修改了内存页 , 导致与磁盘页不一致 的现象;

事物特性

a 原子性 , 要么成功, 失败
c 一致性 , 数据库规则保持一致 , 唯一索引前后一致
i 隔离性 , 事物互不影响
d 持久性 , 事物提交后落盘

事务隔离级别

读未提交 , 脏读
读已提交 , 幻读 , 读不加锁写加锁,
可重复读 , mysql默认 , 读快照 , 还是会有幻读 ,mvvc, next-key lock 解决幻读
串行化 , 单线程 , 全部加锁, 安全 效率低

mvcc

在每行数据中加入版本号 , 和undolog指针用于读旧数据
innodb在可重复读下 ,是mvvc解决幻读 , 每次读到的数据都是小于自己事物版本号的数据

select for … update间隙锁 ,写锁, 不让读 , 解决幻读
share 临建锁 , 共享读锁 , 可以读 , 不能写 , 解决幻读

全局锁

整个数据库上锁 , 只能读 , 用于从库 或数据库备份

表锁

对表上 写锁 或者 读锁 , 读写互斥

自增锁

insert 确定行数的使用行数 , insert … select 不确定行数的 使用表锁

意向锁

表锁, 用来快速判断该表是否加锁 ;
一个事物在加锁时 , 会对表加意向锁, 表示该表已经有锁 , 这样其他事物想加表锁 , 仅需判断意向锁标识 , 不需要逐行扫描 ,
意向锁读写互斥规则相同

innodb锁

记录锁

对索引字段 select … for update 写锁 , 防止插入

间隙锁

select for … update间隙锁 , 对行的左右进行加锁 , 防止插入数据 , 间隙所不排斥

next-key 临键锁

update table set note = ‘1’ where num = 10;
SELECT * FROM table WHERE num = 10 for UPDATE;
记录锁 + 间隙所 , 如果是num为普通索引 , 防止仍有 num=10的数据插入 , 将 10附近的记录都上锁 ;
如果是唯一索引 , 只加记录锁 ;

B+ tree 和 b tree 区别

b树数据放在每个节点上 , b+ 放在叶子节点 , 非叶子节点只放索引, 树层数更少 , 效率更高 ;
b+底层用双向链表连接叶子节点 , 更适合查询 ;

为什么不用红黑树

红黑树比b+的树要高

索引优化

使用数字类型索引 , 比字符串索引效率更高 , 例如ip地址,
实现: 多增加一列字符串转int 或者 字符串增加索引前缀

聚簇索引 非聚簇索引

聚簇索引为索引和数据放在一起 , 非聚簇索引不放在一起 ;
innodb 的主键是聚集索引 , 是树的子叶节点包含一行的所有数据 ; 普通索引为非聚簇索引, 仅包含当前索引字段的值和唯一索引id , 需要再去查唯一索引树;
myisam的非聚集索引 , 唯一索引和普通索引的叶子结点都不记录数据 , 只记录指针;

聚集索引优点 , 使用主键索引可以一次定位到数据 , 可以使用索引覆盖,
聚集索引缺点 , 主键索引维护成本大, 普通索引需要二次查询 , 自定义主键插入导致数据迁移
btree 与 聚簇

联合索引

a_b_c 会生成 a , a_b , abc 3个索引 , 所以可以从左向右匹配 ,

索引失效

索引碰到范围查询条件会失效

索引覆盖 / 下推

覆盖 : 仅查询索引字段的值
下推 : 减少回表次数 , 查询索引时 ,就对其他列的条件进行判断 , 符合的再去回表 , using index condition
索引下推原理

页的预读机制

innodb按照数据页进行读取, 放到bufferpool中, 一次读取extend(64个数据页) , 根据多个读请求的目标数据页是否相邻 , 判断是否可以合并读请求 , 将下一个extend的数据页读出放到bufferpool中
预读机制

bufferPool

bufferpool lru

bufferPool和changebuffer
innodb采用了lru , 并进行了老生代和新生代优化, 新加入得数据页优先放到老生代 ,减少预读失败的后果, , 优先淘汰,
对全表扫描引起的缓存池污染 , 使用了老年代加 滞留时长双标准

MySQL的free、flush、LRU链表
free 存放 未访问的数据页 , flush存放脏数据页 , lru

readview

配合redolog 实现 读快照

行锁升级为表锁

未使用索引或者索引失效将导致加表锁
行锁升级表锁

innodb 和 myisam区别

myisam只能用表锁 , 不支持事物

分库分表

垂直/水平 ,
事务无法保证 , 跨库join问题
分库后查询 , 排序
数据一致性 , 数量 , 关键字段信息
例如订单, 通过uid取模 , 尽量保证同一个用户和用户订单都在一个库 , 商家查询订单 , 冗余一张商家订单表 , 通过商家id取模

主从复制

主节点dump线程主动推binlog ;
3种模式 ,异步(默认) 不管从节点确认 ; 半同步 , 等待其中一个从节点ack消息 ; 全同步 , 等待所有从节点ack;

binlog 格式

sql语句 和 数据行 ;
sql语句日志小, 但类似now()函数在从节点执行时与主节点不相同;
数据行精准, 但是日志量大;

混合模式 , sql语句解析不了的使用数据行;

死锁

超时放弃 , 默认超时50s ;

查询缓存

查询缓存默认不开启,query cache type查看

调优

last quey cost
查询成本消耗值

optimize trace
查询sql优化细节

explain

执行计划 , type表示是否用到索引 , 尽量在range以上或临时表 , 至少index(使用索引 , 不产生回表)

type
const 主键唯一索引进行常量查询
ref 非主键唯一索引进行常量查询
range 索引树范围查询
index 查询索引树
all 全表扫描
extra
using index , 仅对索引树查询, 不需要回表取数据
using index condition 索引下推, 在存储引擎层过滤数据, 减少在应用层传输数据
using where 可能没用到索引, 在应用层过滤,
using join buffer (block nested loop), 连表时坐标用
using filesort , 使用索引外的字段排序
using temp , 使用了临时表

join

a left join b on a.column= b.column, a为驱动表 , 在外循环 , b为被驱动表;
普通嵌套循环 join , 时间复杂度为a.rows 乘以 b.rows ;
joinbuffer , 对外层驱动表, 一次遍历多行数据 放进内存, 减少外层循环次数 , 所以优化要扩大joinbuffer 或者 驱动表尽量选择行数小的表
索引join , 保证内循环column字段为索引 , 时间复杂度 a.rows 乘以 b.column 的index层数 ;

exist in

exist外表驱动 , in 内表驱动 , 尽量用驱动表的索引
exist / in索引

select * from t1 where exists (select 1 from t2 where t1.id=t2.id);

in 使用唯一索引是走索引 , 普通索引不走索引 ;
exist 子查询内表使用索引 , 外表为全表扫描 ;

binlog 维护

查询当前使用的binlog , 删除未用的 , 修改保留周期

深分页

使用主键索引进行分页

什么场景会产生数据库死锁,怎样处理

淘宝线上的的并发插入死锁
唯一索引并发插入;
减少唯一索引 , 短事务 , 保证在一个事务中 , 分布式锁 保证事务串行执行;

唯一索引是否可以插入一条空

可以 , 仅能有一个

表创建后生成什么文件?

frm 记录表结构
innodb 引擎 生成idb 存放元数据 , 索引

聚簇索引怎样存储大文本 , 怎样优化?

mysql text可以存储多少文字_MySQL:InnoDB一棵B+树可以存放多少行数据?
大字段类型, 索引只存储指针 , 数据在外部存储;
阿里开发规范中说明用关联表存储 , 减少大字段文本占用缓存页 , 单表超500w或者2g才使用分表存储;
使用compress函数压缩 , 减少空间量 , 但增加了计算量; 或者对该大文本字段用额外hash索引存储查询 ;

sql

mysql删除重复记录,保留id最小的数据
1.表里有4条数据 , id name 两个字段 , 1条sql 让 name重复的仅保留id最小的,
sql执行前
id name
1 a
2 a
3 b
4 b
sql执行后

id name
1 a
3 b
delete from table where id not in (select id from (selete min(id)from table group by name))t)

group having , oder by执行顺序

Where, Group By, Having, Order by

spring

filter和intercepter区别

区别 :
filter基于servlet,可以拦截静态资源请求 , 不受spring容器管理,
intercepter基于aop反射, 只对controller有效 , 因为是springbean,可以使用bean容器
filter先执行

sevelet生命周期

servlet和tomcat
servlet为单例 , 请求来时初始化调用init方法 , 长时间未使用或服务终止将销毁 , 多个请求为多线程, 所以线程不安全

spring怎样实现的依赖注入?ioc的单例对象被使用时怎样实现的线程安全?

scope默认为singleton ,prototype,request,session和global session
springbean初始化时获取注解设置属性 ,
ioc在一个容器中为单例singletone , 其他情况可以使用theadlocal

springaop

jdk 代理 , 基于接口, 目标类必须实现接口 ; Proxy.newInstance() , invocationHandler
cglib 代理 , 基于实现类 , 生成目标类的子类 , 重写父类方法;
cglib相比jdk执行效率高 , 生成效率低

springioc

beanfactory / factoryBean

两个都是接口 ,
beanFactory提供管理bean规范 ,
bean实现factoryBean , 定义生成bean方式

bean生命周期

初始化 , 赋值 , 初始化完成 , 销毁

解决循环依赖

spring3级缓存 , 分别对应 占位 , 初始化完成未赋值 , 初始化完已赋值

springboot启动流程

判断webapplication类型 , reactive webflux 还是servlet
监听器
生成web环境

自定义runner

redis:

redis工作模型

多路复用中接收的事件会被放到队列中 , 事件处理模块是串行消费的 , 接收socket请求 , 执行命令 , 返回结果

redis6.0 开启多线程 redis6

过期策略

惰性过期 , 查询的时候发现过期 删除 ;
随机过期, 随机获取一部分key , 判断是否过期 , 如果过期率达标 , 会继续随机获取一批key判断;
内存不够时清理 , 插入的时候 , 有几种策略:

  1. 不插入, 报错
  2. 基于所有key ,lru淘汰
  3. 基于所有key , lfu淘汰
  4. 基于ttl的key , lru淘汰
  5. 基于ttl的key , lfu淘汰

性能高原因

减少上下文切换 , 基于内存 , 多路复用

linux io模型

同步bio , 同步nio多路复用 , 异步nio
select 维护了一个1024数组 , 最大监测 1024个socket连接 , 需要遍历数据检查socket状态;
poll使用链表监测更多socket , 但需要遍历所有socket;
epoll 通过事件驱动 , 不需要遍历所有连接 , 解决大量socket连接 但 仅有少数活跃的 情况

阻塞 , 同步

同步非阻塞 , 调用方法后不需要阻塞等待 , 但是会一直轮询调用结果

bio , nio , aio区别

一个网络请求需要两步 , tcp 接收数据 , 将数据从内核拷贝至用户态 ;
bio 在两步都是阻塞 ;
nio 在接收数据时是非阻塞 , 第二步阻塞;
aio在两步都是非阻塞 ;

缓存失效

无效key, 设置默认值, 超短过期时间 ;
热点key不过期 , 惰性缓存设置分布式读写锁 ;
同时过期 , 随机过期时间 ;
根据流量峰谷预热, 提前查进缓存 ;

如何保证缓存一致性

网络波动 或 mysql主写从读的延迟 造成读出旧数据 ;
目标减少并发下造成的旧数据 设置成缓存 , 让旧数据缓存失效;

加锁串行化 , 效率低;
删除缓存 , 更新库 , 睡眠 , 再删除缓存 , 这样可以保证并发下产生的旧数据缓存失效 ;
删除操作异步执行 , 通过binlog ,或者消息队列 ;

redis数据结构

跳跃表 , dic字典 (hashtable) , redisObject 对象结构 ,
redisObject是封装了redis的数据结构, 每个key都会被封装成robjects , 底层表明了具体使用的数据类型和数据结构 ,

string

redis String 原理
redis 封装了 c语言字符串为sds ,通过预留空间, 实现了动态字符串,
降低了c语言中频繁修改字符串内存迁移性能损耗 ,
c语言空字符串结尾, 内容中不能包含空 , 不能存图片等2进制文件. sds的api是二进制安全的,封装了c语言字符串api,符合c语言空字符串结尾;
如果是数字类型使用数字编码 , 实现原子自增等操作

redis 从2.0后支持bit命令, 可以使用bit命令操作 , 实现像布隆过滤器 , 多条件查询, 统计签到功能, 占用空间小 , 性能高

多属性筛选
setbit (“属性 - 值” , “数据主键id” , 1’表示存在’) ;
属性转为位图 , bitop位与运算 , 都满足相当于 并且关系

redis bitmap
签到 , 计算当前日期距开始日期的偏移量 , setbit位 , 置位1就算是签到了 , getbit (offset) 查询签到情况 , bitcount ()统计签到

和java String区别

java String用了长度作为结尾

hash

value小, 或者数量少于512个 , 用ziplist编码 , 数组特性;
或采用hashtable ,
扩容使用 2的n次幂 , 渐进式resize , 扩容时使用标识位记录, 用到哪个桶迁移哪个 , 自带两个hashtable用来resize挪腾数据 , 扩容因子是 1.0 , 小于0.1 会缩容 , 扩容期间查询涉及两个hashtable

list

底层链表 , 可用作异步队列

set

元素少均为整数 ,底层是数组 ,
元素多了是hashtable

zset

跳表
元素少, 用 ziplist , 紧挨的两个元素表示 对象和score;

元素数量超过阈值使用 skiplist 跳跃表 和 dict , dict用来快速查询O(1) , 跳跃表类似btree , 但维护损耗性能更小, 占空间更小 ,每层的节点不是均匀的, 最下层包含所有节点的双向列表 , 可以快速实现范围查询 O(NlogN) , 每个节点都记录自己当前所在的层数 , 也就是说同一个节点可能存在多层, 其中记录的span为下一个节点的距离, 可快速得出当前节点的排名

mysql不使用跳表 , 平衡二叉树原因

跳表适合存储数据少 , 查询耗时比btree慢 ;
二叉树树高 , 基于数组实现, 数据页预读有很多浪费的

持久化

aof rdb

rdb

类似mysql的dump快照, 定时或定量备份全部键值对为二进制文件 , 可fork子进程异步 , 损耗小, 文件小 , 便于容灾, 可能会丢一部分数据

aof

appendOnlyFsync , 类似binlog , 记录操作日志 , 日志先写入aofBuffer , 然后根据aof机制异步刷到磁盘 , 可以是每条命令触发, 也可以是每秒或者交给系统 , 相交rdb 占用空间大 , 损耗大 , 但不易丢失数据 , 日志有可读性 ;

aof重写

aof日志过大 , 可以选择rewrite aof日志 , 由子进程异步执行 ,写时复制原则, 拷贝原日志内容到新日志 , 将原aof日志的命令进行合并 ,减小空间 , 之后异步通知主进程 , 主进程将rewrite开始时记录的aof buffer合并到新的日志文件 ,完成重写 ;
重写机制可自定义 , 增长百分比 或者 文件体积 大于指标

混合

4.0之后, 结合rdb 和 aof , 文件为aof , 一部分是rdb格式 , 一部分是增量的aof日志内容 , 结合了两方面的优点

容灾策略

如果是分布式, 主从复制 主节点宕机数据损坏可能会影响从节点也清空数据 , 建议主节点不开启 持久化 , 从节点开启aof ;
单节点按照流量延迟考虑

高可用

主从机制

从节点向主节点发送唯一标识id和offset , 主节点对比后判断进行全量同步 , 增量同步 ;
全量使用rdb 快照 ;
增量使用aofbuffer , 从节点上次的记录位置开始

哨兵

哨兵是一个特殊的redis服务 , 不存储数据 , 可集群部署 用于监控redis主从, 支持主从命令;
内部有3个定时任务 , 用来同步集群状态 , 心跳检测 , 选举master ;
按照主观和客观配置参数 , 发现主节点下线后 , 会进行master选举 , 通知节点成为master;

集群

redis集群
redis集群模式 解决了海量数据存储和水平扩容问题 , 选举功能 ;
集群包含多个主节点 , n个槽位 , 每个槽位存储一个key , 槽位均分到每个主节点 ;
客户端命令前会对key进行hash取模 , 然后根据key所在的槽位路由到对应的主节点 ;
从节点检测到主节点下线后 , 就会发起选举 , 其他主节点参与选举 ;
水平扩容增加的节点接受其他主节点分给的槽位 ;
cluster create 创建

一致性

redis集群 ap , 不是强一致性 , 主节点执行的命令会异步发送给从节点,
集群分区出现脑裂问题后, 再合为一个集群后, 会丢失未选举成功的分区数据

pipeline

封装多个请求 , 一次发送 , 减少网络io

redis分布式锁

占位思想
redis解析命令模块单线程 , 通过lua脚本保证原子性;

对公共资源进行占位操作即为分布式锁 , 考虑到宕机, 锁时效性等情况, 需要保证加锁时有过期时间和解锁时锁版本一致性 , 锁对应的value值随机性, 解锁时进行value校验 , 对于持有锁时的操作时长过长的情况, 要增加锁的过期时间 , 或者过期时间开始设置的尽量大

set (key ,val随机token , nx不存在才执行 , ex过期 ,10过期时间)

使用lua脚本 -> 使用redisson ,底层使用lua脚本,针对锁起了定时任务watchdog,延长锁的时效性

分布式下 , 由于主从复制延迟 , 主节点宕机后 , 可能会出现 2个客户端给不同主节点加锁成功 , 造成脏数据 , 用红锁解决, 会查询大部分节点, 结果大部分一致才成功

lua脚本命令是什么

避免aba解除他人锁 , 使用redis的eval命令, 判断锁的token是否一致

bigkey

big
value 大 , 或者元素多 , 单节点使用scan 等O(n)操作造成网络阻塞;

布隆过滤器

hash函数 , bit位对应下标 ,
一个keyhash后占用多个位, 所以布隆过滤器的长度预算高于原长度的x倍 ,尽量大, 避免哈希冲突 ,
保证数据一定不存在, 不能保证一定存在 ;
扩容问题 , 定期维护 , 构建两份 , 切换使用 ;

hashes分桶

一个key下的二级key不应过多 , 会造成数据热点 ,
设置缓存时根据总数取模分桶 , 记录桶的数量 , 之后维护的时候先计算桶坐标

Hyperloglog 计算uv

Hyperloglog
pfadd 创建一个hll结构 , pfadd user zhangsan , 记录用户 , pfadd user lisi , pfcount user 统计user的uv为2

系统设计

分布式id生成

分库分表自增 , 起始位不同 ;

雪花算法 , 标志位 , 时间戳 , 机器码 ;
时间回滚 , id重复问题 , 最大服务问题;

大文件上传

文件hash ,分段hash 校验文件是否上传 ;
分片 加序号 异步上传 , 后台拼装, 支持断点续传 , 页面阻塞;

分布式事务

事物协调服务 , 通知参与者开启本地事物 , 再统一提交 或 同一回滚事物

2pc

预备, 提交 , 需要有事物协调服务, 过程出于阻塞 ;

3pc

询问状态 , 预备, 提交 ; 需要有事物协调服务, 非阻塞 , 超时按照提交处理; 会有数据不一致问题

tcc

try confirm cancel
事物执行之后 , 会持续通知参与者 , 直到成功

分库分表动态扩容?

数据分配不均匀怎么做?如何做到动态的扩容缩容?怎么减少扩容缩容时的数据影响范围?
不停机动态扩容

并发抢票

redis list队列做减法 ,原子自增

下单后八小时未支付,发一条消息提醒用户支付

接口幂等性处理

发送消息时发送失败如何处理

发送一条微信消息(发送微信是否是一个模块,是否使用mq,而不是直接使用服务间调用?)
发送消息(生产者)接收消息(消费者)都会对行为进行入库? 发送失败次数超过规定后(失败后检查总次数),
发送给管理员

如何实现秒杀业务?有用到分布式事务吗,如何实现

redis 的list阻塞队列出栈控制资源 ;
订单采用mq实现最终一致性 , 创建订单锁定库存 , 并向mq延时队列发送订单id 消息 , 订单超时后 , 延时队列消息被库存服务消费 , 查验订单状态 , 来决定是否回滚解除锁定或提交真正扣减库存

本地缓存提高qps

一个应用, 一个redis, 应用提供查询接口 实际查询redis , redis最高qps10w ,在不扩展redis硬件的情况下 , 提升至20w qps?
使用本地缓存 , 缓存redis的结果

业务

1.项目介绍

2.项目需求设计经验

3.自己熟悉的技术栈知识

4.团队协作关系处理

5.开发周期控制

其他

生成短链url你会怎么做?
62进制转10进制

hash一致性算法说一下?虚拟节点提前占位 , 环形链表找到真正节点

zgc , jdk11启用的垃圾回收器 , 对超大堆内存支持效果好 , 延迟低

jdk17 lts长期支持版本 , springboot3, spring6默认使用,支持

检查异常和非检查异常 , 检查异常为调用的方法声明抛出了异常 , 需要手动处理 , 不然过不了编译

http 和rpc区别

RPC与Http的区别
双方框架相同, 序列化相同

算法:

十大排序算法
遍历对比 , 冒泡排序 , 稳定, 时间复杂度n^2 , 节省空间
2分递归 , 归并排序 nlogn , 递归需要创建多个子数组
分桶排序 ,

选择排序 , 每次遍历挑选最小的放到队首
快速排序 , 分区处理, 选择基点数(最左) , 后指针r从右向左找比基点小的 , 前指针l从左向右找比基点大的,直到rl等 , 最后交换基点数和r位置元素,基点数左右被分成两部分, 递归处理

Q :三个数组存放着不同元素,放入一个数组中,元素按升序排列

a、b 2个数据集,a数据集和b数据集中每个元素都是对象,每个对象都有一个唯一标示id,id相同则对象相同;通过对比a和b元素产生c集,c集中的元素遵循以下情况:a有b没有的保留,ab交集部分用b的覆盖a的,b有a没有的数据需要额外标记,最终c集合为这3部分数据组成;

rocketMq

高性能

顺序写 , 异步消息 , 分段索引 ,

数据同步方式

同步 , 异步

es

filter不算分,提升性能 , 避免模糊匹配
大量字段场景使用nested和k,v替带;模糊匹配使用多字段替代;空值替代;mapping记录版本号
常用dsl关键字 query , match, filter ,bool, must, agg,sort
索引创建后主分片数不能修改,

solr和es的区别

solr建立索引快,集群需要注册中心;
es建立索引慢,性能高,自带集群,遵循raft选举;

es的深分页会有什么问题?

es深分页
普通查询from , size 不能大于10000
es翻页怎样控制
search after , 不能指定页数
search after 不能指定页码, 不能跳页 , 只能不断向下翻页
scroll api 向下翻页; 快照后新增的文档是无法被查询到的
需要全部文档, 进行数据导出 , 处理的 , 适用scroll api , 不要求实时性, 又节省了性能;
需要分页的, 使用分页参数 , 需要深分页的, 加上search after设置, 节省性能, 保证数据实时性;

queryAndFetch和queryThenFetch区别,es作为集群从存储,查询,是怎样使用的分片,怎样进行汇总,
单分片 queryAndFetch, 不会有数据倾斜问题,

es keyword和text区别
keyword关键字,精确匹配
text会分词

es 两个集群 , 怎么并发保证一致性

比如es两个集群做负载, 订单状态在es中存, 应用需要修改两个es集群订单状态, 在并发下保证一致性 , 用乐观锁 , 修改前去redis里查version, 再去es中修改

profile优化

https://developer.aliyun.com/article/780345 Elasticsearch的TermsQuery慢查询分析和优化

部署

内存磁盘空间比 ; 日志类1:50 , 内存1:16 , 1t数据, 单节点内存32g , 32* 50算出单节点最大数据容量,
index lifecycle management, 索引周期管理工具
动态增加副本分片, 提升吞吐量

kafka(待补充)

kafka入门
Metamorphosis kafka java实现

基于发布订阅 , 消费者拉去数据;
topic是主题 , broker 为集群中的一个实例, 与topic为多对多关系 , 每个topic所在的broker成为该topic的一个分区partition ,
生产者向topic所在的broker负载均衡发消息 , 每个消息可能存在于不同的broker的topic中 .
一个consumer-group对应一个topic , 也就是对应topic的所有分区 , 每个分区的消息只能被同一个consumer-group的一个消费者消费 , 消费者也是轮询从多个partition拉去数据 , 拉取采用适应性自旋 ;

基本概念

主从
broker中选出一个leader , leader负责分区状态 , isr列表 , 副本信息 , ;
同一个topic的partition 的broker中选出一个区的leader, 其余为follower ,
isr
isr是一个队列 , 存放了同步状态正常的follower , 可配置至少有几个follower

key的分发

指定分区 , 指定key进行hash取模 , 未指定key自增取模

分区分段+索引

每个topic-partition 都会在kafka上保存消息 , 消息由segment描述 , 一个log文件记录了所有数据, 名称本文件记录的第一条消息offset , 一个index文件 , 记录了消息offset和在log文件中的offset , timeindex记录了index的位置
当segment满足3个条件任意一个 , 就会再记录一个segment , log或index文件过大 , log超过默认保存时间;

ack

partition的leader拿到消息后将同步给follower , follower拿到消息后会给leader发送ack ;
可选
1.不接收follower的ack
2.接受其中一个follower的ack
3.接受isr中所有的follower的ack, 保证生产者消息不丢失

防止生产者数据丢失

确保有一个follower ;
设置ack all , 等待所有follower同步完成 ;
设置producer发消息失败重试次数无限大 ;

幂等性

生产者本地保存topic-partition的序列号 , 生产消息时带着序列号 , broker也在本地维护了序列号, 确认保存后会对序列号自增 , 进行对比 , 如果序列号小于broker的或大于1个版本以上的 , 将会拒绝消息

事务性

在幂等性基础上 , 增加了跨topic - partition的 transactionId , 该id保证生产者对同一个topic下的多个partition发送消息 , 要么全部成功 , 要么全部失败的原子性 ;
当producer宕机重启后, 或者增加了新的producer后 , 保证旧的producer事务失效 ;
消费者因为消费消息的不可控 , 只能在应用层保证事务性 ;

顺序写和零拷贝

读取时 , 减少了用户态和内核态的数据拷贝 , 通过dma(direct memory access) 从文件拷贝到cpu内存, 用户态共享cpu内存中的数据 ;
write时 , 数据从文件拷贝到cpu内核 , 通过dma拷贝到socket , 然后再发送到网卡;
send时, 减少了socket到网卡拷贝 , 数据从文件拷贝到cpu内核 , 然后再通过dma拷贝到网卡 , 仅将偏移量信息发送给socket;

kafka采用了顺序写 , 减少了寻址时间 ,

consumer rebalance

kafka 中的每个broker 启动时带着一个coordinator , 用来进行该group中的leader选举和决定该组消费者消费哪个分区;
consumer group leader的coordinator会成为group中使用的coordinator;

当该组的消费成员变动 , 或者topic分区增加 , 或者又订阅了其他的topic , 就会进行rebalance , 重新选举和决定消费分区 ;
成员变动包括主动和被动 , 主动为消费成员发消息通知coordinator, 被动就是coordinator通过定期心跳发现消费成员下线 ;
过程为先对所有成员进行选举 , 选举成功后 , 向所有成员发送他们要进行消费的分区 ;

避免重复消费

进行rebalance时, 可能会丢失consumer的ack , 导致重复消费 , consumer可以通过公共存储来判断消息唯一id ;
consumer也有可能被误判成下线 , 消费者拉去两条消息的间隔超时就会判断为下线 , 需要减少消费者一次拉去的最大消息数量, 或者自定义offset消费

zookeeper的作用

保存分区 , isr , 副本的信息 ; 实现集群选举

springcloud

feign重试策略

网关用的什么,gateway和zuul的区别

?springcloud用的什么版本?
gateway使用webflux, 异步 ,底层用的netty,并发性能高,

springcloud用了哪些组件

nacos的通讯协议

服务雪崩概念

限流、熔断介绍

flink

有界,无界流,
sql, table api,
cheakpoint , state, time, window
jobmanager , taskmanager
JobManager:类似spark中master,负责资源申请,任务分发,任务调度执行,checkpoint的协调执行;可以搭建HA,双master。

TaskManager:类似spark中的worker,负责任务的执行,基于dataflow(spark中DAG)划分出的task;与jobmanager保持心跳,汇报任务状态。

flink有许多connector

flink集群部署

https://blog.csdn.net/weixin_44385486/article/details/124197370

hbase

https://www.cnblogs.com/guohu/p/13138868.html
入门HBase,看这一篇就够了
jvm应用, 列式数据库, 亿级以上使用hbase, 不支持事务 , 基于hdfs存储, 需要hadoop , 存储日志, 适合聚合运算, 自带webui
master salve架构, zookeeper为注册中心
table (createTable, modifyTable, removeTabl), 列簇columnfamily(qualifier) (addColumn, modifyColumn, removeColumn) , Region ,data(get, put, delete, next, )
hwal , 保证region 从内存刷磁盘故障时的完整性, wal失败, 则丢弃数据
hfile, hbase索引 行键(row key),列键(column key)和时间戳(timestamp)为索引, 记录了hdfs数据

行键设计: type + 时间戳 , 避免都分配到一个region上造成数据倾斜
列簇: metric + 标识
连接池hpool, scan扫描非一次性取回全部数据

日志优化

hadoop

分布式系统架构,
namenode元数据 , datanode数据节点
yarn
管理任务资源分配
resourcemanager 集群资源管理 nodemanager管理节点资源, , applicationmaster 管理单个任务应用
resourcemanager 中有队列, 生产中每个业务团队使用自己的队列, 不影响其他人

hive
将结构化数据, 提供sql方式查询, 转化为mr的计算任务

doris

doris介绍
百度贡献给apache, mmp应用 类似clickhouse, 替代了kylin+ hbase , clickhouse, es等架构方案

通过mysql客户端连接, 执行sql
fe 处理请求, java应用, 主从部署 ha
be存储计算, c++应用,

可通过表字段聚合配置, 在增删改时进行预聚合, 加速聚合运算

未整理

setnx方法解锁时发现不是自己的锁,解锁失败,已经写入redis的数据怎么回滚?

如果有一百万个cpu密集型的任务需要进行计算,除了获取到线程的,其他全阻塞等待吗?

http连接池怎么做的资源隔离的?

java面试题2021相关推荐

  1. 最新Java面试题2021年,常见面试题及答案汇总

    2021最新Java面试题[附答案解析]java面试题及答案2021,java2021最新面试题及答案汇总,2021最Java面试题新答案已经全部更新完了,有些答案是自己总结的,也有些答案是在网上搜集 ...

  2. Java面试题-2021

    Java面试题 1.MyCat 1.什么是数据库分片 2.MyCat的作用? 3.MyCat和MySQL的区别? 4.什么是分库分表? 5.如何设计分库分表 (mycat) 2.MongoDB 1.M ...

  3. java面试题2021最新

    1 java的跨平台: 概念:java编写的程序一次编译后,可以在运行在任何操作系统上 原理:java的跨平台关键是借助jvm,JVM是一个"桥梁",不同的平台对应不同的jvm(如 ...

  4. java机试题---2021(算法)

    1.功能描述:数组的循环移位, 输入:{a,b,c},2 输出:{b,c,a} public static void main(String[] args) {String[] sArr = getC ...

  5. Java面试题2021,智慧树java程序设计答案

    前言 大厂面试真题向来都是各大求职者的最佳练兵场,而今天小编带来的便是"HUAWEI"面经!这是一次真实的面试经历,虽然不是我自己亲身经历但是听当事人叙述后便会深有同感(因为我朋友 ...

  6. JAVA面试题2021最新整理——JAVA基础篇

    点赞.收藏不迷路,转载请注明出处,感谢各位! 目录 8种基本数据类型 自动拆装箱 String static关键字 final关键字 continue.break.return区别 面向对象的三大特征 ...

  7. Java面试题2021,华为java工程师工资

    前言 难道程序员的职业生命线是青春饭?答案是的. 35岁考虑转行,然后35岁又成了一个新人,而外国可以做到60岁,啥也不说了,可能是觉得中年大叔油腻,不及小鲜肉便宜,唉,可叹市场更新换代太快,快到我们 ...

  8. Java面试题2021,文末有福利

    正文 做了 3~5 年编程开发,你已经积累了不少项目经验,扩宽了技术广度,也许已发力成为团队管理者.到了这个阶段,大家却常有这种感受:感觉自己卡在瓶颈进步缓慢,技术水平很难像早期一样实现大幅突破? 其 ...

  9. Java面试题2021,java搞笑段子

    什么是 CAP CAP 定理最初是由加州大学伯克利分校的计算机科学家埃里克·布鲁尔(Eric Brewer)在 2000 年的 ACM PODC 上提出的一个猜想,也因此被叫做布鲁尔定理.后来在 20 ...

最新文章

  1. el-input怎么绑定回车事件
  2. 某40岁程序员找工作,因技术老旧被拒绝,竟泪洒当场!
  3. ubuntu14中 memcached安装与使用
  4. How I can Built A-Z index site map in my website
  5. jQuery-给ul添加了li之后,添加的li并没有绑定点击监听怎么办?
  6. 专业人士提升数据中心职业生涯的6件事
  7. mysql权限与安全
  8. oracle 怎么拼,ORACLE 简化拼接
  9. [转]用C/C++扩展PHP详解
  10. iStream DDS
  11. python etree xpath_【Python】爬虫之使用etree进行xpath元素定位
  12. matlab 输入矩形序列,从python调用Matlab函数:“初始值设定项必须是矩形嵌套序列”...
  13. 拓端tecdat|R语言惩罚logistic逻辑回归(LASSO,岭回归)高维变量选择的分类模型案例
  14. DHCPv6 snooping
  15. XGBoost如何画出树分裂图,用代码绘制多棵CART回归树
  16. sandboxie游戏不能运行在虚拟环境中如何解决_Mac系统运行“exe”文件最简单的解决办法...
  17. 解决vim-plug无法下载插件或者插件下载过慢的问题
  18. Revit中创建基于线的砌体墙及【快速砌体排砖】
  19. 云队友丨刘润:拼命成长,才不浪费一场危机
  20. landsat5数据下载1985年中国地区

热门文章

  1. python qq群_python qq群机器人怎么弄
  2. 检查手机端还是非手机端,做m站和pc站的适配
  3. 2023年中国十大软件公司排行榜 2023国内软件公司排名前十强
  4. 问题: 一维Schrodinger方程的双线性Strichartz估计的最佳性
  5. TensorFlow学习--LeNet5神经网络
  6. error LNK2019: 无法解析的外部符号 “public: __cdecl ...,函数 ...中引用了该符号解决办法
  7. 那你讲一下LeakCanary的原理
  8. 企业微信推送消息延迟_一种基于企业微信的消息推送方法与流程
  9. 算法分析---寻找丑数
  10. 多线程并发在电商系统下的追本溯源-电商实战