java 面试消息题1-13
1. Redis 线程模型, 及为什么redis 这么快?
1.Redis虽然是一条一条处理命令的(单线程),但是redis把每一条命令分成了很多个小命令,对这些小命令是多线程执行的。
2. IO 多路复用 - 可以用别人用过的IO。
3. 基于内存的key-value 的nosql数据库。
Redis 的数据类型:
2. 消息中间件作用,存在的问题, 如何解决这些问题?
重复消费:
比如kafka一下子会消费10条数据然后提交,告诉kafka当前这个Consumer A 在这个Broker B的 Partition 1上消费到offset 10上面了。 结果在第消费完第3条时候挂了,或切换到一个backup的Broker上面了。这时候又会从第一天开始消费, 前三条就会重复。
解决方案:
1 业务上解决(幂等性), db 里面加unique key constraint
2 用分布式锁,redis set Nx , 保证每相同的消息只能有一个拿到redis锁。
丢消息:
主从切换的时候, 发送到主broker上的消息A还没来的及同步的从broker上面, 也没有来得及被consuser 消费掉。这时候切换到从broker上时消息就会丢失。
使用acks 参数配置解决丢消息的问题:
acks = 0 ,leader收到消息,但是还没有来得及被消费就挂了。
acks = 1 ,leader收到消息并写入磁盘但是这里有一个问题,万一Partition Leader刚刚接收到消息,Follower还没来得及同步过去,结果Leader所在的broker宕机了,此时也会导致这条消息丢失,因为人家客户端已经认为发送成功了。
acks = all ,Partition Leader接收到消息之后,还必须要求ISR列表里跟Leader保持同步的那些Follower都要把消息同步过去,才能认为这条消息是写入成功了。
kafka没有丢消息但是你的业务处理失败了,也相当于丢消息了。可以修改为自己提交,等业务也处理完成后才手动commit。
消息积压:
解决思路: kafka 把当前的consumer 改一点代码不作任何业务, 直接转发到其他拥有多个partition的broker上面去-> 在被多个其他的consumer去处理业务代码。
顺序消费:
自己写业务代码, 将相关的需要有顺序的消息发到同一个partition里面去。
3. 什么是分布式锁?
用一个锁来保证每次只有一个线程在执行一段代码,就行jvm中的synchronized代码块,有些代码段不能被多个线程同事执行,例如减库存。
分布式锁一般用redis 的setnx来实现,setnx 只有返回true的那个线程才算拿到锁了。
利用的是redis执行命令是单线程的原理, 同一时间多个命令发送到redis,redis内部一定是排好序按顺序一个一个的执行。所以只有最前面的那个才能拿到锁。
setnx实现分布式锁也会存在一定问题,例如如果一个线程拿到了锁,但是他又挂掉了,其他线程就永远无法拿到锁了。 解决问题 + 超时事件, 必须同一行加, 后面追加的会存在原子性问题。
+ 超时事件也存在问题, 超时事件设置多长呢 ?
设置太长了, 如果其挂了, 需要让其他线程等待太长时间了
设置太短了,有些程序就行需要执行比较长事件
假如你设置了一个固定的超时时间, 但是程序的运行时间就是比你设置的时间长,到时间之后就需要把锁释放了,这时候其他的程序就行进到这段加锁的代码里面来。
1. Redission - 解决分布式锁的问题。
2. Zookeper - 解决Redisson 锁同步问题,即redisson1刚刚给Redis(Master)加好锁还没来的及同步到Slave,这时候Master挂了。当Slave切换成Mater以后,锁就不存在了,其他的Redission可以加到锁了,这时候就出现了多个线程同时进入锁的问题呢。
Zookeper 解决分布式锁问题- zookeeper原生特性就行为分布式锁定制的
为什么可以解决问题 ?
1. 选举机制会选举日志最多的那个follower作为下一个leader
2. 只有半数以上的follower日志写成功后才算redission对redis的加锁成功。
(1)用create 同一个临时节点来实现分布式锁的加锁问题, create成功的那个算加锁成功
(2)用create 临时有序节点 + watcher监听通知机制,可以代替自旋的问题,临时节点序号最小的拿到锁。
3. 用create临时节点加上失效时间来失效超时效果
4. 什么是分布式事务 ?
5. 什么是分布式session?
spring session
tomcat-redis-session-manager
6. Mybatis ?
Mybatis 的四种mapper 方式:
package (priority)
resourse
url
class
myBatis 一级缓存基于sqlsession的, 二级缓存, 跨sql session的。
7. 什么是java的死锁,如何排查死锁?
java 死锁:拥有锁的两个线程相互等对方的锁
如何排查找出死锁:
在idea 离有个快照可以生成堆栈信息:
在server中使用 jstack 命令后面跟要检查的进程号码如下8480
jstack <pid>
8. java 如何保证线程顺序执行?
使用join来保证线程顺序
thread1.join()意思是让main线程等待thread1结束,然后再继续往下执行。
9. Zookeeper中集群角色有哪些?
Leader :负责读,写,选举投票权
follower:负责读,选举投票权
observer:负责读,没有投票权
10. Zookeeper节点有哪些?
持久(有序),临时(有序)
客户端断开节点是否会被删除
11. 集群支持动态增加机器码 ?
zk 支持, 但是支持不是很好,停机器,加配置
全部重启,影响服务
挨个重启:zab zk 原则广播协议
12. 有哪几种集群方式 ?Redis 有哪些适合的场景?Redis相比memcached相比有哪些优势 ?
单机,集群,伪集群(所有节点在一台机器上)
分布式session, 接口幂等性(唯一性),缓存,排行榜,队列(订阅)
memcached: 字符串,没有持久化,速度慢,并发
Redis: 其他类型,可持久化,熟得快,单线程
13. 什么是缓存击穿,什么时候缓存雪崩 ?什么是布隆过滤器?
缓存击穿 - 用户查询的数据在redis里面没有,必须进数据库查询。(恶意攻击)
缓存雪崩 - 大量数据在redis里面同时失效了,例如大量的数据设置的有效时间是一样的(系统本本身)。
缓存null值,下次请求,虽然你请求的值在数据库找不到,但是可以在缓存里面找到值,值为null。
布隆过滤器 - gauwa,可能在集合中,绝对不在集合中。
简单的说,当需要判断一个值(“abc”)是否存在时候,把这个值进行取hash值,用三个不同的函数可以算出三个不同的数值,再把这三个值对应的二进制数字位数上的值标记为1.只有判断处这三个位置的值都为1的时候这个值才有可能存在。只要有一个位上的值为0则表明该值肯定不存在。