2024年05月08日
kafka如何保证顺序消费,假如:一个房间ID1001,产成大量的数据,如何顺序存储到kafka,如何保证消费端多线程消费的时候也是保证顺序的
kafka没用过,主要是使用的rabbitmq,对于需要保证顺序消费的业务,可以只部署一个消费者实例,然后设置 RabbitMQ 每次只推送一个消息,再开启手动 ack 即可。多个消费者实例,我不会。
Redis中用set数据结构,存储了10w左右的数据,如何合理的获取出来
bigKey 数量太多了所以不能用命令全部取出 可以用sscan命令一点点去读取。京东有个开源的 bigKey 探测系统。
A,B,C三个字段,创建联合索引,说一下可能走索引的所有情况的sql,越多越好
abc ,ab,a,ac(abc字段都在,无论顺序如何都会走索引,ab,ac,a会部分走索引,其他情况不走索引)
- 区分度高的字段放在前面,区分度低的字段放后面
- 最左前缀,联合索引遇到范围匹配会停止,不会再匹配后面的索引字段
- MySQL优化器为了适应索引,会调整条件的顺序。
- 怎么判断是用到了3个字段的索引,而不是只用到前两个字段的索引呢?有个非常简单的方法,看执行计划的索引长度。
线上有什么问题的处理令你很深刻吗,介绍一下
随便编了一个:正则表达式回溯的问题。
Redisson的watchDog,底层的源码有了解吗,说下抢到锁的线程执行流程,以及没有抢到锁的线程如何进行处理的
watchdog 就是jdk会起一个定时任务 每10s(没记错的话)会去执行:看下key还存在吗 存在的话进行一个续签。因为redisson在进行lock的时候 如果你没有设置超时时间 它会默认设置30s的过期(为了让你的服务挂了之后 锁能释放掉)watchdog就是为了让这个30s能不断的续签下去(如果你的服务挂了 watchdog自然就不会执行了)
如果抢到锁,整个lock就结束了。如果没有抢到锁的话。首先会注册监听一个redis的一个释放锁的事件并将自己阻塞掉(目的是为了不占用cpu,阻塞自己让出cpu给别的线程执行)。当收到锁释放消息的时候 就会进入一个while 进行自选尝试去获取锁(如果设置了过期时间的话 还会判断是否已经超时 超时也会直接结束)。获取获取到 就结束 还是没获取到 自己会根据获取的到ttl跟waitime 进行比较取一个较小值用于创建有一个信号量 再将自己阻塞掉。等时间到了 在在这个while循环里面在进行上面的步骤 直到获取锁 或者 超时(如果有设置waitTime的话)
b树,b+树的特点,以及优缺点
B树的特点的 非叶子节点也会有数据存储。而B+树的话 数据只会在叶子节点上。如此的话所以 B+树的层级会小点而且数据都在叶子节点所以查询的所要经过的层级都一样所以查询的速度更文档。还有叶子节点都同一层,相互之间有关联形成了链表结果 对范围查找的速度会更快
处理过线上的内存泄露的情况吗,说下你的应急方案以及处理方法
确定是内存泄漏还是内存溢出啊,泄漏的话 你应该感觉不出来,只有内存泄漏导致了内存溢出了 你去查原因 才会发现内存泄漏的问题。如果是溢出的话。简单点 你可以先用 jstat -gcutil 看下fgc的情况 如果很频繁的话 用 jmap -histo:live 看下前几个存活的对象有多少 如果有个对象占比很多的话 就是这个对象内存溢出了 可能是哪里list或者map存储着 要看下代码 这个对象的引用。如果看不出来的话 只能打印内存快照生产 hprof文件 在用mat之类的工具分析
线上CPU100%问题的排查,如何处理和定位
- top 查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。
- top -Hp 进程号 查看java进程下的所有线程占CPU的情况。
- printf "%x\n 10 后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.
- jstack 进程号 | grep 线程ID 线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了
- jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
- jmap -dump:format=b,file=filename 进程ID导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多。
java中的锁默认是什么模式,java设计者为什么设计锁的默认方式为非公平锁
- 恢复挂起的线程到真正锁的获取还是有时间差的,从开发人员来看这个时间微乎其微,但是从CPU的角度来看,这个时间差存在的还是很明显的。所以非公平锁能更充分的利用CPU的时间片,尽量减少CPU空闲状态时间
- 使用多线程很重要的考量点是线程切换的开销,当采用非公平锁时,当1个线程请求锁获取同步状态,然后释放同步状态,因为不需要考虑是否还有前驱节点,所以刚释放锁的线程在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销
- 为了更高的吞吐量,非公平锁是比较合适的,因为节省很多线程切换时间,吞吐量自然就上去了; 否则那就用公平锁,大家公平使用。
线程池的核心参数有哪些,如果提交一个任务到线程池,创建的线程数是多少,如何保证线程池的线程进行存活的机制,结合源码讲一下
corePoolSize + allowCoreThreadTimeOut + keepAliveTime、workQueue、maximumPoolSize、RejectedExecutionHandler、threadFactory
当一个线程处理完当前任务后,就会开始去阻塞队列获取任务,只不过,在调用poll或take方法之前,会判断当前线程池中有多少个线程,如果多于核心线程数,那么当前线程机会调用poll()并设置超时时间来获取阻塞队列中的任务,这样一旦时间到了还没有获取到任务,那么线程就不会阻塞了,并且没有业务执行,那么线程就会运行结束,也就是回收了。
MVCC机制实现原理,数据结构以及实现
mysql表中每行列都有2个隐藏列 分别保存了 对应的事务id和redo log日志的索引。每当对数据进行修改时 修改后redo log日志的索引会指向老的数据。这样才形成了 redo日志的版本链, 版本链和readview 才实现了mvcc。才实现了mysql的可重复读和读已提交2个事务隔离级别。readview的话 有几个重要的结构:当前事务、事务id数组(包含目前活跃的事务id)最小事务id、最大事务id。然后还要说清楚readview的运行逻辑。 其实这个还是八股 就是之前我提到的 mysql的ACID是如何实现的中的事务相关内容。可以多背背
说下零拷贝的原理,零拷贝的实现方式有那些,那些系统运用到了零拷贝
零拷贝就是没有把数据从一个存储区域拷贝到另一个存储区域。
DDD
- 说下DDD的核心思想是什么,你们落地是采用的那种模式,战略方式,战术方式了解吗,说下俩种方式的区别
- 你们DDD架构的包结构以及每个包的职能划分,调用如何设计得
- DDD设计过程中,你们如何设计核心领域,子领域,领域边界的