- 学习kafka消息队列,zookeeper
- 复习数据库MySQL
- 复习Redis,特别关注集群部分,主从复制部分
- 准备明天美团面试
一:消息队列的作用/优点
- 解耦
接触消费者与生产者之间复杂的调用关系
2. 异步
a系统查询完成之后调用b系统,只有等b系统返回才能继续这是同步。a系统查询完成之后直接把消息放入消息队列,然后就不用管了,这是同步。
3. 削峰
A 系统调用 B 系统处理数据,每天 0 点到 12 点,A 系统风平浪静,每秒并发请求数量就 100 个。结果每次一到 12 点 ~ 13 点,每秒并发请求数量突然会暴增到 1 万条。但是 B 系统最大的处理能力就只能是每秒钟处理 1000 个请求,这样系统很容易就会崩掉。这种情况可以引入消息队列,把请求数据先存入消息队列中,消费系统再根据自己的消费能力拉取消费。
二:kafka如何保证高可用?
三:如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性?
要保证消息不被重复消费,其实就是要保证消息消费时的幂等性。幂等性:无论你重复请求多少次,得到的结果都是一样的。例如:一条数据重复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性。幂等性问题只有在修改的操作时才会产生。
写MySQL
- 写之前先查询这条消息是否依旧存在,如果存在,那么update
- 将MySQL列设置唯一索引
写Redis
Redis本身就是set的操作,因此可以确保幂等性。
四:如何处理消息丢失问题?
五:如何保证消息传输的顺序?
什么是分布式?
分布式是指通过网络连接的多个组件,通过交换信息协作而形成的系统。
而集群,是指同一种组件的多个实例,形成的逻辑上的整体。
CAP理论
分布式系统不可能同时满足一致性,可用性,分区容忍性。
- 一致性
多个数据副本保证数据一致 - 可用性 每一次请求都能在有限的时间内正确的返回
- 分区容忍性
网络分区是指由于网络故障,分布式的系统划分为多个区域,每个系统内部可以进行通讯但是区域之间无法进行通讯
如何权衡
分区容忍性实际上是不可缺少的。因此我们只能在一致性和可用性之间抉择。如果是涉及钱等敏感资源的我们当然需要保证其一致性。
BASE理论
https://juejin.im/post/5b2663fcf265da59a401e6f8
- 基本可用
- 软状态
- 最终一致性
分布式事务
- 什么是分布式事务?
事务是一系列小操作的集合。分布式事务的本质是为了确保分 布在不同计算机的数据库保持数据的一致性。
- 实现方法
两阶段提交
阶段1:协调者询问所有参与者事务是否执行成功
阶段2:如果所有事务均执行成功那么向所有参与者发送commit事务命令
缺点:
- 整个过程同步阻塞,需要等所有的节点全部完成才能释放资源
- 单点问题。过于依赖协调者,如果协调者出现问题,那么影响很严重
- 没有数据强一致性,如果commit阶段出现网络故障,那么将导致某些节点commit,而某些节点未commit,会使得数据不一致。
- 过于保守。任一节点失败则判断为整个系统失败,没有完整的容错机制。
三阶段提交
针对两阶段提交,3阶段提交进行了一下的改进:
- 将准备阶段拆分为canCommit与preCommit阶段。加入canCommit阶段的目的是为了在不锁资源的情况下,先确定是否所有节点都具有执行事务的能力
- 引入了超时机制,体现在a. precommit后协调者如果超时未收到参与者的ack,那么他会发送要求所有参与者回滚的命令。precommit之后如果参与者未收到协调着的commit命令,那么他会默认直接commit(这里当然也存在数据不一致的问题,但是没办法,情况很极端,无法严格实现)
阶段1: canCommit
阶段2: preCommit
阶段3: doCommit
本地消息表+消息队列
在本地数据库中存在一个消息表,由于是在同一个数据库,因此利用本地的事务就可以确保消息被放到消息表,后将消息传到消息队列,消息队列再到另一个系统的消息表。整个过程利用本地数据库的事务+消息队列。
分布式锁
锁的作用在于实现资源的互斥访问。在单机,锁可以通过语言的内置功能实现,而在分布式领域我们的实现方式有:
- Redis setNX
- Redis RedLock
- 数据库唯一索引
- zookeeper有序节点
分布式一致性算法
- paxos算法
- raft算法
zookeeper
- 什么是zookeeper
- zookeeper提供哪些功能
- 说说zab协议
参考:
https://juejin.im/post/5b26648e5188257494641b9f
2pc 3pc 好文 https://www.zhihu.com/search?type=content&q=%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4
wiki paxos算法 https://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95
从我个人目前的情况出发,Mybatis等等框架已经不适合再去看源码了,就看看以前的总结,然后一些面经吧
Mybatis是什么?
Mybatis是一个半ORM框架,他的内部封装了JDBC,在开发的时候我们只需要写sql语句(并且支持动态sql),就可以得到一个数据对象,而不需要像是使用jdbc一样,处理 加载驱动,建立连接, 获取statement等于业务逻辑无关的操作了。半ORM框架在于他是sql获取对象,而不是对象查询得到对象(如 Hibernate )
Hibernate与Mybatis的区别?
Mybatis中 #{} 与 ${} 的区别是什么?
- {}里的值替换成了变量的值
- #{} 在处理时,会将#{} 替换为? ,再通过preparestatement的set方法进行赋值。使用#{}可以有效的防止sql注入式攻击。
分页
分页可大致分为2种实现,
- 物理分页:利于MySQL的limit语句实现
- 逻辑分页:先将数据全部查询的内存中,然后再过滤
在MyBatis中有4中具体的实现:
- 基于数组
- 基于RowBounds
- 基于sql语句
- 基于拦截器(插件)
查看详情:
https://blog.csdn.net/chenbaige/article/details/70846902?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
一级缓存二级缓存
- 一级缓存:
基于sqlsession级别的。在进行数据查询时,先优先查询此sqlsession拥有的一个cache,这是一个基于
HashMap的数据结构。生命周期为在同一个sqlsession会话内生效 - 二级缓存:
基于Mapper级别的。和一级缓存的流程一样,也是默认基于一个cache的数据结构,不过区别在于,他也可以使用外部的缓存应用进行缓存。如Redis。
一级缓存是默认开启的。二级缓存可通过配置进行开启。对于任何的增删改的操作,都会导致缓存被清空。
三种执行器
- SimpleExecutor
每次执行一次update或者select就开启一个statement对象,用完之后立即关闭。 - ReuseExecutor
重复使用statement对象。 - BatchExecutor
执行update(jdbc批处理不支持select)时,一次处理一批。
动态SQL
Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能,Mybatis 提供了 9 种动态 sql 标签
trim|where|set|foreach|if|choose|when|otherwise|bind
Mybatis逆向工程
通过数据库的表结构,自动的生成单表相关的所有mapper.xml,mapper.java,以及POJO(java bean)文件,这样我们就只需要关注自身的业务逻辑了。
Mybatis延迟加载
延迟加载,也就是懒加载,更加直白的说,就是 按需加载
Mybatis支持association关联对象与collection关联集合的延迟加载。association是指如
class student {
int id;
String name;
Teacher teacher;
}
class teacher {
int id;
}
其中一个student对应一个teacher,这就被称为assocation,这个时候我们可以先差student的数据,等到用到teacher时再延迟加载teacher。
参考:
https://blog.csdn.net/eson_15/article/details/51668523
https://blog.csdn.net/hbtj_1216/article/details/52876201
实现原理
是基于CGLIB动态代理模式实现的。当调用获取到的student.getTeacher.getId()方法时,在getTeacher这一步检测teacher是否为空,如果为空,则查询数据库。这就实现了 延迟加载了。