[TOC]
吾生也有涯,而知也无涯。
缺乏一个正确的、高效的学习方向
希望能够站在一个相对正确的角度去看待要学习的内容
(1)、业务维度
ssm —> 分布式 —> 微服务 [需要学习那些知识]
(2)、非业务维度
怎么样除了业务维度,提升自己的技术能力、技术修养、技术内容,然后对业务有一个相辅相成的作用。
1、ConsurrentHashMap 源码解读
ConcurrentHashMap
- 数据结构
- 数组 + 链表 + 红黑树
- 数组是基础结构;key相同的时候用到链表;链表长度过长则使用红黑树;
- HashTable 是在整个数组上加Sync,锁的粒度较大;
- CHM使用comparaAndSwap 粒度只到数组对象级别,只在数组对象上加锁,比较友好;
- CHM 在扩容时使用单线程 保证线程安全;同时其他线程也不会闲着,会帮忙协助进行数据重新赋值。
2、Spring boot 核心原理
1、Spring boot相对Spring来说解决了那些痛点?
2、Spring boot的自动装配是怎么实现的?
- Spring boot是Spring的升级版,整合集成了Spring framework、IOC、AOP等优秀思想。主要解决的是SpringMVC在常见web项目是复杂繁琐重复的JAR依赖、版本排查、web.xml、springMVC.xml等配置文件工作,使用“自动转配”的方式,一键化创建springWeb项目(仅需配置application.properties或application.yml文件)。详情可参考
- 自动装配使用到的注解:
- @SpringBootApplication
- @Configuration
- @EnableAutoConfiguration
- @Bean
- @Import / @ImportSource
- @ComponentScan
- 怎么将第三方的类放到容器中?规范的作用来了。统一加载类的路径或规范(spring.factories),通过一个个”start”,来加载 xxxAutoConfiguration 来批量装配
3、JVM 基础学习
屏蔽操作系统
Java内存分解和各作用
堆 : 存放 对象和数组;
本地方法区:常量池和类、方法的描述;
java虚拟机栈:java方法的栈帧;
本地方法栈:本地方法的栈帧(C、C++等)
PC 计数器:
垃圾回收
判断一个对象是否为垃圾
- 引用计数法
- 可达性分析
有哪些垃圾回收算法可进行回收
- 标记-清楚
- 复制
- 标记-整理
- 分代回收
通过垃圾收集器进行对垃圾回收算法进行实现
- 新生代收集器:Serial、ParNew、Parallel Scavenge
- 老年代收集器:CMS、Serial Old、Parallel Old
- 整堆收集器: G1
评价垃圾回收算法的优劣
JVM参数
- 有哪些常用的参数
- 堆、方法区、Java虚拟机栈、启动时间等
- 有哪些常用的参数
JVM命令
- jps、jinfo、jmap、jstack
JDK一些工具
日志: gc-viewer、gceasy
堆: MAT、PerfMa、heaphero.io
4、AQS分析学习
AQS = AbstrarctQueuedSynchronizer
1、数据安全产生的原因?怎么解决
- 可见性
- JMM[java内存模型]、valatile、synchornized、lock
- 有序性
- 指令重排序 synchornized、lock
- 原子性
- 要么都执行,要么都不执行
- AtomicInteger、AtomicDouble等原子类
- synchornized、lock
2、锁的前后流程是怎么设计的?
- lock
- 竞争锁
- ``` java
// 简单示例 int state = 0 if (state == 0) { // 表示获取锁 } else { // 表示竞争锁失败,等待 }
Code1
2
3
4
5
6
7
8``` java
final void lock() {
if (compareAndSetState(0, 1))
// 设置当前线程为“锁的拥有者”
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
- ``` java
- 没有竞争到锁的线程存储
- 队列、链表、数组等;java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 使用链表
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
- 队列、链表、数组等;
- 没有竞争到锁的线程阻塞
- wait
- condition
- lockSupport.park()java
1
2
3
4private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
- 竞争锁
- unlock
- 释放锁
- state –
- 唤醒
- lockSupport.unpark()
- 释放锁
3、可重入锁是干什么用的?怎么实现的?
- 某一个程序在进入A锁后,如果还需要进行B函数中,此时如果B函数也需要加锁,如果不是可重入锁,则在这里会造成死锁现象;
- Lock的实现是设置了一个”state”标识加锁与否,另有一个标识当前“锁的拥有者”是否为当前锁,如果是同一个则可以进入另一个锁,就不会造成死锁了。
5、RabbitMQ从工作机制到延时队列的实战
1、RabbitMQ工作机制
2、延时策略回调
- CAP
- 消息中间件- 保证服务可用,也就是AP;
- 消息中间件运用场景
- 解耦;
- 异步;
- 削峰/填谷
- 顺序保证;
- 可靠传递;
- 最终一致性;
- 事件编程;
- 消息中间件带来的风险
怎么实现延迟队列?
- TTL + 死信
RabbitMQ中的死信和处理方案
- 死信:
- RabbitMQ consumer主动拒绝消费;
- 消息的TTL(time to live)过期;
- 消息在加入队列时超过队列中消息的长度;
- 解决方案:
- 当消息成为死信后,若该队列配置了死信交换机,则将该消息按规则转发给该交换机(主题交换机);若没有配置死信交换机,则消息丢失,不再处理(消息消失)
6、跨域单点登录原理分析及实战
一次登录,导出乱跑
CAS流程图,也是单点登录标准流程图
Token的生成有讲究的
- 确保安全性
- 能验证其正确性
JWT:Java web Token
基于不同的加密算法,以及author、timestamp、xxx参数等 ——> 作为参数 ——> 生成一个结果
Java:引入jwt包 —— 使用对应的工具类
sessionId的有效性问题
session 假设20分钟
sso.com sessionId/token
order.com sessionId/token
user.com seeeionId/token
彼此的有效性就要考虑了(其中一个过期了,其他的怎么办?)
- 子模块先到期了,sso没有过期,怎么办?
此时不用办,sso没有过期,此时有全局的sesson和token,子模块来访问时,再重新颁发token即可,并创建局部session对象;
- sso过期了,子模块没有过期,怎么办?
续签的操作。重新创建一个全部的session对象,或者token重新生成一次,然后颁发给子模块;
- 注销的问题,意味着sessionId过期了,所有子模块全部过期,并且需要重新登录
一次注销,全部注销
在sso维护一个列表,记录所有子模块的信息,然后注销所有的子模块;
在微服务场景下【1000个服务】——》sso.server ——》是不是没有服务都要写一份处理和sso交互的代码呢?
答案是不需要。我们可以设计一个解决方案:
sso.client ——》需要进行单点登录的服务就可以直接引入这个包,然后进行相应配置即可。
sso-server.jar ——》部署
sso-client.jar ——》需要用到的引入jar包,并进行一些简单的配置
Central Authentiacation Service: CAS 单点登录方案
Auth2协议 是怎么实现单点登录的?
Spring Security是怎么实现的?
总结
单点登录要做的事情:
- 单点登录(SSO系统)是保证各业务系统的用户资源的安全;
- 各个业务系统获得信息是,这个用户能不能访问我的资源;
- 单点登录,资源都在业务系统模块这边,不在SSO系统中;
- 用户在给SSO服务器提供用户名、密码等信息后,作为业务系统并不知道这件事;
- SSO随便给业务系统返回一个ST(Service Ticket),那么业务系统是不知道这个ST是用户伪造的,还是真实有效的。
- 所以,业务系统需要拿着这个ST去SSO系统中验证一下,用户给我的ST是否有效,有效的话我才能让这个用户访问我的资源;
7、百万级数据ID生成方案
1、分布式ID
不管在什么地方(何地),在什么时候(何时),都要保证这个ID是全局唯一的,
2、分布式ID生成方案
(1)、数据库自增ID
单独一个数据库表记录和产生ID
自增步长 和 起始值
订单ID, 1、2、3、4……
泄露我们公司敏感的信息 — 瑞幸
不该返回的信息不要返回
根据ID 猜测出订单量
缺点
不利于扩展
会暴露敏感信息
(2)、UUID
日期时间、 时钟序列、 全局唯一机器ID、算法生成 — hash冲突 (基本上唯一,不保证唯一)
有5个版本
- 1、日期+mac地址;会暴露mac地址,私密性不好
- 2、DCE;
- 3、基于字符的MD5算法;
- 4、随机的UUID;
- 5、基于字符的SHA1算法;
缺点:
- mysql是个B+树,而UUID是随机的,不适合做数据库主键;
- 可读性低,字符串占内存等等
(3)、redis
- incr() 函数
- 单线程 — 命令执行 — 每个命令都是原子性 (redis 6.0后有了”多线程”,这个是针对网络请求、数据处理,命令执行的话还是单线程)
(4)、snowflake
1位符号bit + 41位时间戳bit + 10位机器bit + 12位序列号bit = 64bit — > 10进制数字
可套用公式 — 自己实现雪花算法
8、分布式Dubbo框架的核心探秘
1、Dubbo的本质是RPC服务框架;
2、RPC的理解及各阶段的实现方式;
3、用一个小时实现自己RPC通讯机制;
4、学习、理解RPC的演化过程;
RPC:remote procedure call
序列化和反序列化 (因为网络跨应用调用,底层是通过二进制字节码传输)
动态代理 — 》 保护 和 增强 方法;
spring[IoC, AOP]
Mybatis[mapper文件接口, 动态代理]
Dubbo[SPI, RPC]
Tomcat
spring cloud一些组件实现 [Feign, Ribbon]