面试就是这么简单,offer拿到手软(三)—— 常见中间件框架面试题,es,redis,dubbo,zookeeper kafka 等

news2024/11/27 12:34:15

在这里插入图片描述
面试就是这么简单,offer拿到手软(一)—— 常见非技术问题回答思路

面试就是这么简单,offer拿到手软(二)—— 常见65道非技术面试问题

面试就是这么简单,offer拿到手软(三)—— 常见中间件框架面试题,es,redis,dubbo,zookeeper kafka 等

面试就是这么简单,offer拿到手软(四)—— 常见java152道基础面试题

文章目录

  • 一、消息队列
    • 1.1 常见消息队列优缺点
    • 1.2如何保证消息队列高可用?
      • 1.2.1 使用kafka使用集群模式
      • 1.2.2 确保不重复消费
      • 1.2.3 确保消息可靠性传输
      • 1.2.4 如何保证保证消息顺序性
      • 1.2.5 如何设计消息中间件
  • 二、分布式搜索引擎
    • 2.1. es分布式架构原理
    • 2.2. es读写流程原理
    • 2.3. es优化
  • 三、分布式缓存redis
    • 3.1 为什么要用分布式缓存?
    • 3.2 常见问题
    • 3.3 redis介绍以及与memcached的区别
      • 3.3.1. redis是单线程工作模型
      • 3.3.2. redis和memcached 区别
      • 3.3.3. redis高可用原因
      • 3.3.4. redis数据:
      • 3.3.5 .redis过期策略
      • 3.3.6. redis高并发高可用的保证
      • 3.3.7 .redis持久化
      • 3.3.8. redis横向扩容
      • 3.3.9 一致性hash算法(有虚拟节点,为解决热点数据)
      • 3.3.10 redis cluster,hash slot算法
      • 3.3.11 缓存雪崩、穿透
      • 3.3.12 数据库双写不一致
      • 3.3.13 redis并发竞争
  • 四、dubbo:
    • 4.1 dubbo工作原理
    • 4.2. 支持协议
    • 4.3.dubbo负载均衡策略
    • 4.4.集群容错
    • 4.5.动态代理策略
    • 4.6 自设计rpc框架
  • 五、zookeeper
    • 5.1. 适用场景
    • 5.2.分布式锁
  • 六、分布式session
  • 七、分布式事务
  • 八、设计一个高并发的系统架构
  • 九、分库分表
  • 十、读写分离、主从复制、同步延时问题
    • 10.1. 读写分离
    • 10.2.主从复制
    • 10.3.主从同步机制
    • 10.4.同步延时问题

一、消息队列

1.1 常见消息队列优缺点

常见消息队列:activemq、rabbitmq、rocketmq、kafka
消息队列的优点: 解耦、异步、削峰
消息队列的优点: 系统可用性降低、系统复杂性提高、一致性问题

1.2如何保证消息队列高可用?

1.2.1 使用kafka使用集群模式

1.2.2 确保不重复消费

  • 使用offset序号(zk实现)
  • 保证幂等性(使用数据库表主键)

1.2.3 确保消息可靠性传输

  1. 如何解决消费端弄丢问题?
    关闭自动提交offset,改为手动提交offset
  2. 如何解决kafka本身弄丢的问题?
    leader宕掉
    topic设置replication.factor值大于1,要求partition必须至少2个副本
    kafka服务端设置min.insync.replicas值大于1,要求leader至少感知到有至少一个follower跟自己保持联系
    producer(生产者)端设置acks=all,每条数据必须是写入所有replica后,才认为写入成功
    producer端设置retries=MAX,一旦写入失败,无限重试,卡在这里

1.2.4 如何保证保证消息顺序性

  • kafka保证写入一个partition中的数据是一定有顺序的,生产者指定的一个key的数据一定会写入到一个partition中
  • 消费者从partition中取出数据也是一定有顺序的
  • 多线程处理时可能会顺序出错,设定内存队列,hash分发时,同一key分到同一队列

1.2.5 如何设计消息中间件

  1. 支持扩容
  2. 数据落磁盘
  3. 可用性
  4. 数据可靠性

二、分布式搜索引擎

elasticsearch 即 es

2.1. es分布式架构原理

es存储数据的基本单位是索引index
index -> type -> mapping -> document -> field
1个index能被分成多个shard,分布在不同的机器上,shard类比kafka,有主从性(备份)
写只能主,读可以主从

2.2. es读写流程原理

写入内存buffer和translog

  • buffer快满了或一定时间后,将buffer中数据refresh到一个新的segment file中(先进入到os cache,一般1s执行一次)
  • refresh持续执行后,当translog达到一定体量时,触发commit操作(buffer中现有数据全部refresh到os cache中,清空buffer,将一个commit point写入磁盘文件,标识对应的segment file,将os cache中数据fsync到磁盘)
  • 可以调用api手动执行flush操作(整个commit过程即flush)
  • translog也是先进入到os cache中,默认5s持久化操作一次
  • 删除操作,标识del标记,逻辑删除,非物理删除
  • 更新操作,即先标记原有数据del,重新写入一条数据
  • 定期执行merge操作,当segment file多到一定程度的时候,es就会自动触发merge操作,将多个segment file给merge成一个segment file

2.3. es优化

  1. 加大分配给es的内存(数据量的体量最好小于或等于分配给es的内存)
  2. 数据预热,对于大量搜索的数据,定时的查询一次,将数据存入到es内存中
  3. 优化存入filesystem cache的数据,只存入用于搜索的数据
  4. 冷热分离,尽可能的将热数据放到一个索引,冷数据放到另一个索引中去,防止热数据被冷数据从cache中冲掉

三、分布式缓存redis

3.1 为什么要用分布式缓存?

为了高性能和高并发使用缓存(使用场景:数据字典)

3.2 常见问题

1)缓存与数据库双写不一致
2)缓存雪崩
3)缓存穿透
4)缓存并发竞争

3.3 redis介绍以及与memcached的区别

3.3.1. redis是单线程工作模型

3.3.2. redis和memcached 区别

	1)Redis支持服务器端的数据操作:
	Redis相比Memcached拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。
	这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。
	2)集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是redis目前是原生支持cluster模式的

3.3.3. redis高可用原因

  1. 非阻塞IO多路复用模型
  2. 纯内存操作
  3. 避免了多线程的频繁上下文切换问题

3.3.4. redis数据:

	String、Hash、list、set、zset

3.3.5 .redis过期策略

  1. 定期删除+惰性删除
  2. 内存淘汰
    1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错
    2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
    3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key
    4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
    5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
    6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除

3.3.6. redis高并发高可用的保证

	主从架构、读写分离、水平扩容
	哨兵sentinel机制
	redis集群数据丢失问题:
	1)异步复制
	2)集群脑裂
		min-slaves-to-write 1
		min-slaves-max-log 10
	选举:
		slaves priority优先级 -> replica offset -> run id

3.3.7 .redis持久化

	用于故障恢复
	持久化方案:
	AOF:每条数据写入一个AOF文件内,适合做热备
		当AOF文件膨胀到一定体量时,会触发rewrite操作,基于现有redis数据生成一份新的AOF文件,并将原有AOF文件清除
		一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据
		AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复
		但:
			AOF日志文件通常比RDB数据快照文件更大
			AOF开启后,支持的写QPS会比RDB支持的写QPS低
			做数据恢复的时候,会比较慢
	RDB:每隔一定时间,生成一个快照,适合做冷备
		RDB对redis对外提供的读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可
		但:
			时间间隔问题,数据不全

3.3.8. redis横向扩容

	redis cluster支撑N个redis master node,每个master都可挂载多个slave node

3.3.9 一致性hash算法(有虚拟节点,为解决热点数据)

3.3.10 redis cluster,hash slot算法

	cluster有固定的16384个hash slot,对每个key计算CRC16值,然后对16384取模,可以获取key对应的hash slot
	redis cluster中每个master都会持有部分slot,增加一个master,就将其他master的hash slot移动部分过去,减少一个master,就将它的hash slot移动到其他master上去
	移动hash slot的成本是非常低的,客户端的api,可以对指定的数据,让他们走同一个hash slot,通过hash tag来实现

3.3.11 缓存雪崩、穿透

3.3.12 数据库双写不一致

3.3.13 redis并发竞争

分布式锁+时间戳

四、dubbo:

4.1 dubbo工作原理

		第一层:service层,接口层,给服务提供者和消费者来实现的
		第二层:config层,配置层,主要是对dubbo进行各种配置的
		第三层:proxy层,服务代理层,透明生成客户端的stub和服务单的skeleton
		第四层:registry层,服务注册层,负责服务的注册与发现
		第五层:cluster层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
		第六层:monitor层,监控层,对rpc接口的调用次数和调用时间进行监控
		第七层:protocol层,远程调用层,封装rpc调用
		第八层:exchange层,信息交换层,封装请求响应模式,同步转异步
		第九层:transport层,网络传输层,抽象mina和netty为统一接口
		第十层:serialize层,数据序列化层
		工作流程:
		1)第一步,provider向注册中心去注册
		2)第二步,consumer从注册中心订阅服务,注册中心会通知consumer注册好的服务
		3)第三步,consumer调用provider
		4)第四步,consumer和provider都异步的通知监控中心

4.2. 支持协议

		1)dubbo协议
			单一长连接,NIO异步通信,基于hessian作为序列化协议;适用的场景就是:传输数据量很小(每次请求在100kb以内),但是并发量很高
		2)rmi协议
			走java二进制序列化,多个短连接,适合消费者和提供者数量差不多,适用于文件的传输
		3)hessian协议
			走hessian序列化协议,多个短连接,适用于提供者数量比消费者数量还多,适用于文件的传输
		4)http协议
			走json序列化
		5)webservice
			走SOAP文本序列化

4.3.dubbo负载均衡策略

		1)random loadbalance 权重
		2)roundrobin loadbalance 轮询
		3)leastactive loadbalance 自动感知
		4)consistanthash loadbalance 一致性hash算法

4.4.集群容错

		1)failover cluster模式
		失败自动切换,自动重试其他机器,默认就是这个,常见于读操作
		2)failfast cluster模式
		一次调用失败就立即失败,常见于写操作
		3)failsafe cluster模式
		出现异常时忽略掉,常用于不重要的接口调用,比如记录日志
		4)failbackc cluster模式
		失败了后台自动记录请求,然后定时重发,比较适合于写消息队列这种
		5)forking cluster
		并行调用多个provider,只要一个成功就立即返回
		6)broadcacst cluster
		逐个调用所有的provider

4.5.动态代理策略

	默认使用javassist动态字节码生成,创建代理类,但是可以通过spi扩展机制配置自己的动态代理策略

4.6 自设计rpc框架

	注册中心 -> 动态代理 -> 负载均衡 -> 网络通信

五、zookeeper

5.1. 适用场景

	1)分布式协调
	2)分布式锁
	3)元数据/配置信息管理
	4)HA高可用性

5.2.分布式锁

	redis实现 -> 叫做RedLock算法,是redis官方支持的分布式锁算法
		互斥(只能有一个客户端获取锁),不能死锁,容错(大部分redis节点存活这个锁就可以加可以释放)
		1)第一个最普通的实现方式,如果就是在redis里创建一个key算加锁
		创建锁 SET my:lock 随机值 NX PX 30000
		释放锁 一般可以用lua脚本删除,判断value一样才删除
		2)RedLock算法
		使用redis cluster集群,为避免上一方法redis宕机问题
	zookeeper实现
		zookeeper保证只有一个人获取到锁(创建临时节点),某一线程获取到一个锁后执行一定的操作后释放锁,其他线程如果没有获取到这个
		锁就对这个锁注册一个监听器,感知到锁被释放后再次重新尝试取锁

六、分布式session

1.tomcat + redis
	在tomcat配置文件配RedisSessionManager属性
2.spring session + redis
	spring-session-data-redis.jar
	jedis.jar

七、分布式事务

1.两阶段提交方案(XA方案)
	有一个事务管理器,先询问后执行
2.tcc方案(try、confirm、cancel)
	1)Try阶段:对各个服务的资源做检测以及对资源进行锁定或者预留
	2)Confirm阶段:在各个服务中执行实际的操作
	3)Cancel阶段:业务方法执行出错,那么这里就需要进行补偿,执行已经执行成功的业务逻辑的回滚操作
3.本地消息表
	通过zookeeper、mq和数据库来做,数据库中有个业务表和一个消息表
4.可靠消息最终一致性
	基于mq实现,阿里的rocketMQ
	1)A系统先发送一个prepared消息到mq,如果这个prepared消息发送失败那么就直接取消操作不执行
	2)如果这个消息发送成功,那么接着执行本地事务,如果成功,向mq发送确认消息,如果失败就告诉mq回滚消息
	3)如果发送了确认消息,那么此时B系统会接收到确认消息,然后执行本地的事务
	4)mq会自动定时轮询所有prepared消息回调你的接口
	5)如果系统B的事务失败了,自动不断重试直到成功
5.最大努力通知
	1)系统A本地事务执行完之后,发送个消息到MQ
	2)这里会有个专门消费MQ的最大努力通知服务,这个服务会消费MQ然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统B的接口
	3)要是系统B执行成功就ok了;要是系统B执行失败了,那么最大努力通知服务就定时尝试重新调用系统B,反复N次,最后还是不行就放弃

八、设计一个高并发的系统架构

1.系统拆分
2.使用缓存
3.使用mq
4.分库分表
5.读写分离
6.es

九、分库分表

分库分表中间件: cobar、TDDL、atlas、sharding-jdbc、mycat
range分法(按时间分) 扩容快,但是大部分的请求,都是访问最新的数据
哈希分法(以某一字段取模分) 可以平均分配给库的数据量和请求压力,但扩容麻烦
垂直拆分:把一个有很多字段的表给拆分成多个表,或者是多个库上去
水平拆分:一个表的数据给弄到多个库的多个表里去,但是每个库的表结构都一样,只不过每个库表放的数据是不同的,所有库表的数据加起来就是全部数据
不停机迁移分库分表:
	双写迁移方案

十、读写分离、主从复制、同步延时问题

10.1. 读写分离

	基于主从复制架构,简单来说,就搞一个主库,挂多个从库,然后我们就单单只是写主库,然后主库会自动把数据给同步到从库上去。

10.2.主从复制

	主库将变更写binlog日志,然后从库连接到主库之后,从库有一个IO线程,将主库的binlog日志拷贝到自己本地,写入一个中继日志中。
	接着从库中有一个SQL线程会从中继日志读取binlog,然后执行binlog日志中的内容,也就是在自己本地再次执行一遍SQL。

10.3.主从同步机制

	mysql实际上在这一块有两个机制,一个是半同步复制,用来解决主库数据丢失问题;一个是并行复制,用来解决主从同步延时问题。

10.4.同步延时问题

	1)分库,将一个主库拆分为4个主库,每个主库的写并发就500/s,此时主从延迟可以忽略不计
	2)打开mysql支持的并行复制,多个库并行复制,如果说某个库的写入并发就是特别高,单库写并发达到了2000/s,并行复制还是没意义
	3)重写代码,插入数据之后,直接就更新,不要查询
	4)如果确实是存在必须先插入,立马要求就查询到,然后立马就要反过来执行一些操作,对这个查询设置直连主库。不推荐这种方法,你这么搞导致读写分离的意义就丧失了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1286946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DAPP开发【09】NFT交易市场开发(hardhat测试)

测试文件下新建market.js文件 扁平化,将所有依赖放在tmp.sol,可以去给他人使用 npx hardhat flatten > tmp.sol 测试文件 const {expect} require(chai); const {ethers} require(hardhat);describe(Market,async function(){//定义三个合约&a…

long转int类型转换问题

在业务代码中排序时需要根据日期排序,写了如下代码 sorted((o1, o2) -> {String str1 null;String str2 null;try {Field field getField(fieldMap, configBO.getCodeName());str1 String.valueOf(field.get(o1));str2 String.valueOf(field.get(o2));} ca…

kubectl获取命名空间下所有configmap集合的方法

前言: 获取单个configmap并忽略特定字段的操作可参照:kubectl获取ConfigMap导出YAML时如何忽略某些字段。 要获取命名空间下所有ConfigMap并忽略特定字段,你可以使用kubectl命令与例如yq这样的工具结合使用来忽略或删除不需要的字段。以下是…

分布式ID服务实践

背景 分布式场景下需要一个全局 ID 来标识唯一性,比如在单数据库时通过表唯一主键即可实现唯一 ID,分库分表时就需要全局唯一 ID。 业务对唯一 ID 的要求如下: 全局唯一性 不能出现重复的 ID 号,既然是唯一标识,这…

CGAL的周期三角剖分(相关信息较少)

CGAL的周期二维三角剖分类旨在表示二维平面上的一组点的三角剖分。该三角剖分形成其计算空间的分区。它是一个单纯复体&#xff0c;即它包含任何k-单纯形的所有关联j-单纯形&#xff08;j<k&#xff09;&#xff0c;并且两个k-单纯形要么不重叠&#xff0c;要么共享一个公共…

数据结构与算法-D2D3线性表之顺序表

线性表&#xff1a;包含若干数据元素的一个线性序列&#xff0c;特征如下&#xff1a; 1&#xff09;对非空表&#xff0c;a0是表头&#xff0c;无前驱&#xff1b; 2&#xff09;an-1是表尾&#xff0c;无后继&#xff1b; 3&#xff09;其他元素仅且仅有一个前驱&#xff0c;…

Day02 Liunx高级程序设计2-文件IO

系统调用 概念 是操作系统提供给用户使其可以操作内核提供服务的一组函数接口 用户态和内核态 其中 ring 0 权限最高&#xff0c;可以使用所有 CPU 指令&#xff0c; ring 3 权限最低&#xff0c;仅能使用 常规 CPU 指令&#xff0c;这个级别的权限不能使用访问硬件资…

解决 vite 中 import.meta.globEager is not function 的问题

本人正在重构两年前搭建到一半的博客网站&#xff0c;相关依赖都很陈旧&#xff0c;用到了 npm-check-updates 检测项目可升级依赖&#xff1a; 升级完成后解决完依赖发现控制台报错 import.meta.globEager is not function解决方案&#xff1a; vite版本降至4.3.0 亲测有效&…

Shell数组函数:数组(二)

关联数组 注意&#xff1a;先声明关联数组 一、定义关联数组 方法一 #一次赋一值 #数组名[索引]变量值 [rootlocalhost ~]# declare -A ass_array1 [rootlocalhost ~]# ass_array1[index1]pear [rootlocalhost ~]# ass_array1[index2]apple [rootlocalhost ~]# ass_array1[ind…

gpt阅读论文利器

1. txyz.ai 读论文 严伯钧 3. consensus 两亿科学论文的资源库. 用英文. 中国经济发展, 美国加州没有,减肥没有. 2. chrome插件 gpt sidebar 3. gpt academic 论文润色和学术翻译 ,一键输出公式. 英语口语8000句. 托福备考计划表. 百词斩托福. 薄荷外刊. 分区笔记精读法.…

Container容器技术简介

本文介绍了容器技术出现背景&#xff0c;docker技术与容器编排技术的简单说明 背景 在传统项目的生产环境中&#xff0c;迁移一个用户态进程往往非常麻烦&#xff0c;因为一个用户态进程背后会附带这非常多例如函数库、中间件等的依赖项&#xff0c;但又没有像apt和yum一样的…

广州华锐互动:钢铁厂烫伤事故3D模拟急救演练提高企业应对突发事故能力

随着工业化进程的加快&#xff0c;钢铁行业作为国家经济的重要支柱产业&#xff0c;其安全生产问题日益受到社会各界的关注。近年来&#xff0c;我国钢铁企业不断加大安全生产投入&#xff0c;但事故频发的现象仍然时有发生。为了提高钢铁企业应对突发事故的能力&#xff0c;确…

如何使用llm 制作多模态

首先将任何非字符的序列信息使用特殊n个token 编码。 具体编码方法以图像为例子说明&#xff1a; 将固定尺寸图像如256256 的图像分割为1616 的子图像块。 将已知的所有图像数据都分割后进行str将其看做是一个长的字符&#xff0c;而后去重后方式一个词表。 使用特殊1024 个tok…

推荐6款本周 火火火火 的开源项目

本周 GitHub项目圈选 节选自微博、知乎、掘金等社区。 &#x1f525;&#x1f525;&#x1f525;本周推荐的开源项目是&#xff1a; kopia 日常备份工具 screenshot-to-code 截屏生成代码 MiniSearch 全文搜索 clone-voice 声音克隆 NvChad 高颜值终端 DB-GPT-Hub 文本到…

关于 Kubernetes中Admission Controllers(准入控制器) 认知的一些笔记

写在前面 工作中遇到&#xff0c;简单整理记忆博文为官方文档整理涉及内置准入控制的分类理解理解不足小伙伴帮忙指正 人活着就是为了忍受摧残&#xff0c;一直到死&#xff0c;想明了这一点&#xff0c;一切事情都能泰然处之 —— 王小波《黄金时代》 为什么需要准入控制器 准…

怎样的软件测试工程师才算“大神“?“我“的测试之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 个优秀的软件测试…

6.Eclipse里下载Subclipse插件

方法一&#xff1a;从Eclipse Marketplace里面下载 具体操作&#xff1a;打开Eclipse --> Help --> Eclipse Marketplace --> 在Find中输入subclipse搜索 --> 找到subclipse点击install 方法二&#xff1a;从Install New Software里下载 具体操作&#xff1a;打开…

RPC基础

RPC基础知识 RPC 是什么? RPC&#xff08;Remote Procedure Call&#xff09; 即远程过程调用&#xff0c;通过名字我们就能看出 RPC 关注的是远程调用而非本地调用。 为什么要 RPC &#xff1f; 因为&#xff0c;两个不同的服务器上的服务提供的方法不在一个内存空间&…

【从零认识ECS云服务器 | 快速上线个人网站】一、ECS概述

首先我们来说什么是服务器&#xff0c;服务器本身就是一种电脑&#xff0c;和我们日常使用的电脑一样&#xff0c;同样具备CPU、内存、硬盘、网卡、电源等硬件&#xff0c;但是由于服务器是24小时不间断运行&#xff0c;所以需要更加强大的配置来支撑其运行&#xff0c;以保障公…

【c】16进制数转化为10进制数(计算方法在最后,大家也可以上网搜索视频,视频更详细,谢谢)

#include<stdio.h> #include<math.h> void trans(char arr1[],int arr[],int n) {puts("请输入16进制的数");for(int i0;i<n;i){scanf("%c",&arr1[i]);arr[i](int)arr1[i];}for(int k0;k<n;k){if(arr[k]>65&&arr[k]<7…