总结test
1.IO流
|-- 字节流
操作任何类型文件
|-- 字符流
操作纯字符类文件
|-- BIO
传统IO流,阻塞型的,也就是BIO,当执行IO流时,CPU只能等待执行完当前任务,才能去执行其他线程任务
|-- NIO
非阻塞型IO流,CPU可以同时执行多个IO流线程任务
2.集合
|-- Collection
|-- List
|-- ArrayList
以数组为基础结构,内存空间连续,查找快,增删慢
|-- LinkedList
双向链表实现:(内存不连接) 查找慢,增删快.
实现原理:
双向链接列表实现(双向链表).
1. 每增加一个新元素, 链表内部,就会创建一个新的节点对象,通过节点保存新增的元素.
并且让上一个节点记录新节点...
优点: 增和删除元素时,很快,
只需要新增的节点记录下一个节点, 上一个节点记录新增节点...
删除元素,也只需要改变节点和及节点之间的关系. 不再设计元素的移动和数组的扩容
查找元素,尤其是查找中间元素时,很慢的. 需要逐个遍历每一个节点,进行比较慢...
|-- Set
特点: 无序,元素不可重复.
|-- HashSet
HashSet(通过hashCode方法获取哈希码值,如果哈希码值相等,那么调用equals方法来比较两个元素是否相同....)
哈希表实现. -> hashCode equals (存储的元素对象一般要重写这两个方法来比较两个元素是否相同)保证元素的唯一性
|---LinkedHashSet
使用链表保存了元素插入的位置.
代码示例:
@Override
public int hashCode() {
System.out.println("调用了hashCode方法...");
return age + this.name.hashCode();
}
@Override
public boolean equals(Object obj) {
System.out.println("equals....");
if (obj instanceof Person) {
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
} else {
return false;
}
}
|-- TreeSet (如果是自定义的集合类型继承TreeSet ,那么要重写comparable方法...来确定元素两两之间的顺序)
二叉树实现(左小,右大)
还可以给元素进行自然排序-> 使用到元素的比较功能(Comparable compareTo) String Integer
方式一:
自定类实现Comparable compareTo
方式二:
直接给集合指定比较器. Comparator compare
代码示例:
@Override
public int compareTo(Person p) {
System.out.println(this + "--compareTo--" + p);
if (this.age > p.age) {
return 1;
} else if (this.age < p.age) {
return -1;
}
return this.name.compareTo(p.name);//字符串之间的比较比较的是它们对应ASC-II码中的数字....
}
|-- Map (接口)
特点: 一次存储2个对象,键和值, 建立键值的映射. 保证键的唯一性.
|---HashMap
键的唯一性: 哈希表机制.
存储键是, 键的hashCode 和equals 检验键是否重复.
如果重复, 键和新值建立映射,和旧值解决映射...
HashMap的底层数据结构原理: 数组+双向链表 (JDK 1.7)
数组+双向链表 (JDK 1.8)
|-- 如何进行数据存储的,根据建获取数据值的基本原理
|---TreeMap
键的唯一性,还可以给键排序.
方式一:
键(类)实现Comparable ->compareTo
方法二:
键(自定义类) 不具备方式一.
直接给集合指定比较器 Comparator -> compare
20150828-->理解这些集合内部的存储原理以及优缺点.....
2.多线程
1.提高cpu资源利用率
2.提升用户体验
服务区.
如何创建线程.
方式一:
继承Thread
方式二:
实现Runnable(推荐)
runnable和thread的区别: http://www.oschina.net/question/565065_86563
2:线程执行原理
由于java只是操作系统上执行的一个进程.
程序是cpu执行的,只有一个cpu如何实现多线程
1:MyThread类的线程和main方法主线程抢cpu执行权,抢到之后,执行一段时间,如果在特定的时间没有执行完,交给另外一个程序执行。
2:在物理上只有一个cpu的情况下,JVM采用抢占cpu资源,给不同的线程划分指
定时间片的方式来实现,同一时间片只有一个线程执行(cpu纳秒级别如同看电影,其实是图片)
--|Java中隐含的两个线程: 1.main方法-主线程 2.GC垃圾回收机制线程....
--|线程的细节:
1:一个Thread实例就是一个对象,Thread也有变量和方法,也是在堆上生存和灭亡。
2:启动程序的main方法运行在一个线程内,该线程叫做主线程
3:线程启动使用父类的start方法
4:如果线程对象直接调用run方法,JVM不会当做线程来运行,只是普通的方法调用
5:线程启动只能有一次,否则抛出运行时异常
1:main方法中使用MyThread类调用了2次start方法,启动了2个线程,运行抛出异常,该异常是运行是异常(编译通过运行错误)
一旦线程的run方法执行完毕后,该线程就不能重新再启动.该线程已经死亡.
6:为什么要继承Thread类,Thread类可以创建对象
1:可以直接创建Thread类的对象并启动该线程,但没有重写run方法,什么也不执行
7:匿名内部类的线程实现方式
8.模拟QQ聊天与视频......
9:新线程被启动后(调用start方法后),线程之间的的执行并不是按照main方法中的顺序执行,是抢占式,谁抢到cpu(该cpu给该线程分配了特定的时间),谁就执行.
xx20150827 --知识久了不用就很快就忘记了....有需要的话还是要偶尔复习一下的.....o(╯□╰)o....xx
线程中几个常见的方法:
getName() 返回线程的名字
setName(String name) 设置线程对象名
getId() 返回线程的标识 同一个线程对象的id不同
getPriority() 返回当前线程对象的优先级 默认线程的优先级是5
setPriority(int newPriority) 设置线程的优先级 虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现
static int MAX_PRIORITY 10
线程可以具有的最高优先级。
static int MIN_PRIORITY 1 线程可以具有的最低优先级。
static int NORM_PRIORITY 5 分配给线程的默认优先级。
currentThread() 返回CPU正在执行的线程的对象
线程安全问题//使用登记模式来创建单例模式可以解决线程的安全问题....而懒汉式和饿汉式都会存在线程安全问题,需要做同步处理
多线程,修改了共享数据.
同步解决问题
同步代码块
synchronized (this//将当前对象作为锁,或者将某个类.class的字节码文件 作为锁,这样可以保证锁的唯一性) {//被锁住的代码块--意味着在同一个时间只能有一个 线程在执行这部分代码 }
同步方法 -- 函数需要被对象调用,那么函数都有一个所属对象引用,是this,所以同步函数使用的锁是默认是-->this//静态同步public static synchronized Single getInstance() { } 使用的锁是类的字节码文件对象
Lock.lock
unlock
(同步方法可以和同步代码块之间实现相互的转换)
线程生命周期
新状态
可运行
阻塞
运行
死亡
线程的通信机制
wait
notify
notifyAll
生产者于消费者---线程之间的通信
死锁(当多线程之间都有对方想要的资源才能才能执行,却都不愿意先放开自己的资源,这样就会出现死锁的情况...)
如何解决, 银行家算法...
/*
1.main方法就是一个主线程
3:线程池
ThreadPoolExecutor 线程池的参数、工作原理?
下面是ThreadPoolExecutor最核心的构造方法参数
1)corePoolsize 核心线程池的大小
2)maximumPoolsize 最大线程池大小,当队列满了 就会创建新线程直至最大
3)keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程超出有效时间也关闭
4)TimeUnit keepAliveTime 的时间单位
5)workQueue 阻塞任务队列
6)threadFactory 新建线程工厂,可以自定义工厂
7)RejectedExecutionHandler 当提交任务数超过maximumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理
重点讲解
corePoolSize,maximumPoolSize,workQueue三者之间的关系
1)当线程池小于corePoolSize时,新提交的任务会创建一个新线程执行任务,即使线程池中仍有空闲线
程。
2)当线程池达到corePoolSize时,新提交的任务将被放在workQueue中,等待线程池中的任务执行完毕
3)当workQueue满了,并且maximumPoolSize>corePoolSize时,新提交任务会创建新的线程执行任
务
4)当提交任务数超过maximumPoolSize,新任务就交给RejectedExecutionHandler来处理
5)当线程池中超过 corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
6)当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭
4:分布式系统中的线程安全
|-- 分布式锁
|-- 什么是分布式锁?
分布式锁,是控制分布式系统不同进程共同访问共享资源的一种锁的实现。秒杀下单、抢红包等等业务场景都需要用到分布式锁,我们项目中经常使用Redis作为分布式锁。
|-- 如何实现分布式锁?
1、使用setNX 结合lua脚本命令去加锁,保证原子性
2、加锁的时候需要有客户端id、过期时间(避免死锁)
3、解锁也是使用lua脚本进行解锁,比较解锁的id是否和加锁的客户端id一致,一致的时候才进行删除锁的操作
4、结合redis 哨兵模式实现高可用
3.JVM原理和调优
|-- 类的加载机制
1.加载:
JVM加载.class字节码文件
2.验证
验证.class字节码文件是否合法
3.准备
在方法区中准备内存空间,分配内存空间和初始值
4.解析
将符号引用替换成直接引用
5.初始化
调用类的构造方法,创建实例对象,放到堆内存中使用
|-- JVM内存模型
|-- 方法区
存储类的字节码文件信息、静态变量、常量等
|-- 堆内存
存储实例对象,也是GC回收的内存空间
|-- 栈内存
线程栈,线程运行的内存空间,存储栈帧,线程的内部数据
|-- 什么时候进行压栈和弹栈?
在执行方法时进行压栈,方法执行完回调就会弹栈,遵循先进后出的原则
|-- 调优
|-- 内存调优
|-- 内存泄漏、内存溢出、内存占用过高如何调优?
–>查看当前 JVM 堆内存参数配置是否合理
–>查看堆中对象的统计信息
–>查看堆存储快照,分析内存的占用情况
–>查看堆各区域的内存增长是否正常
–>查看是哪个区域导致的GC
–>查看GC后能否正常回收到内存
|-- CUP调优
–>查看占用CPU最多的进程
–>查看占用CPU最多的线程
–>查看线程堆栈快照信息
–>分析代码执行热点
–>查看哪个代码占用CPU执行时间最长
–>查看每个方法占用CPU时间比例
|-- GC调优
–>查看每分钟GC时间是否正常
–>查看每分钟YGC次数是否正常
–>查看FGC次数是否正常
–>查看单次FGC时间是否正常
–>查看单次GC各阶段详细耗时,找到耗时严重的阶段
–>查看对象的动态晋升年龄是否正常
4.Spring 框架
两个核心内容:IOC和AOP
|-- IOC 控制反转、依赖注入
IOC是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由给Spring框架来管理将对象之间的相互依赖关系交给IOC容器来管理,并由IOC容器完成对象的初始化和注入。
基本原理:
1、启动spring容器,创建上下文对象
2、加载和初始化BeanFactory工厂,提取Bean的配置信息
3、通过BeanDefinition定位和解析需要IOC容器创建和管理的类资源
4、再通过BeanFactory创建Bean的实例对象放到IOC容器中
5、最后通过注解进行实例依赖注入和初始化
|-- AOP 面相切面编程
能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性,
基本原理:
1、在编译时期动态生成代理类
2、基于JDK动态代理对目标类进行增强
3、把那些与业务无关,但被系统所公用的逻辑或功能(如事务、日志等)分离出来,降低模块间的耦合,并提高系统的扩展性和可维护性
5.SpringMVC 框架
工作原理总结:
1、客户端(浏览器)发送请求,直接请求到DispatcherServlet
2、DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler/Controller
3、HandlerAdapter会根据Handler来调用真正的处理器来处理请求和执行相对应的业务逻辑
4、处理器处理完业务后,会返回一个ModelAndView对象
5、ViewResolver会根据逻辑View去查找实际的View
6、DispatcherServlet把返回的Model传给View(视图渲染)
7、把View返回给请求者(浏览器)
6.SpringBoot 框架
|-- 为什么需要SpringBoot?
Spring Boot 优点非常多,如:独立运行、简化配置、自动配置和无需部署war文件等等
|-- 自动配置原理
1、spring boot 启动的时候会通过 @EnableAutoConfiguration 注解找到spring.factories 配置文件
2、找到所有的自动配置类,并对其进行加载,这些自动配置类都是以AutoConfiguration结尾来命名的
3、然后通过 @ConfigurationProperties 注解解析全局配置文件中的属性,并和自动配置类的属性进行绑定
7.SpringCloud 框架与微服务
|-- 什么是微服务?
微服务架构就是将单体的应用程序分成多个应用程序,这多个应用程序就成为微服务,每个微服务运行在自己的进程中,并使用轻量级的机制通信。这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署。这些服务可以使用不同的编程语言,不同数据库,以保证最低限度的集中式管理。
|-- SpringBoot和SpringCloud的区别?
(1)SpringBoot专注于快速方便的开发单个个体微服务。
(2)SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞,分布式会话等等集成 服务
(3)SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系
|-- SpringCloud有哪些核心组件组成?
1、Spring Cloud Eureka : 服务注册与发现
2、Spring Cloud Feign :声明性的Web服务客户端
3、Spring Cloud Ribbon : 客户端负载均衡
4、Spring Cloud Hystrix :熔断器
5、Spring Cloud Gateway :服务网关
6、Spring Cloud Config:分布式统一配置管理
|-- Eureka
注册中心:通过DiscoveryClient发现和注册服务,并且和客户端保持心跳检测,检查各个微服务是否征程
|-- Feign
声明性的Web服务客户端:通过@FeignClient注册声明web服务客户端,通过动态动态代理,构建http请求服务,构建请求链接、请求参数、发起请求、接收返回json并转换成实例对象
|-- Ribbon
客户端负载均衡器:从注册中心读取目标服务列表,对同一接口进行请求计数,把请求均衡分发到列表中的服务
|-- Hystrix
熔断器:当请求某个服务时,如果发生故障,有可能会导致服务血崩,最后整个系统不可用。为避免这种情况,有必要使用熔断器。当发生故障时,可以服务降级、服务隔离、服务熔断。
Hystrix有四种防雪崩方式:
服务降级:接口调用失败就调用本地的方法返回一个空。
服务熔断:接口调用失败就会进入调用接口提前定义好的一个熔断的方法,返回错误信息。相关注解:@FallBack
服务隔离:隔离服务之间相互影响。
服务监控:在服务发生调用时,会将每秒请求数、成功请求数等运行指标记录来。
|-- Gateway
API网关:提供统一的应用服务入口,所有的API请求都需要经过Gateway网关进行转发到具体的服务
作用:统一管理微服务请求,权限控制、负载均衡、路由转发、监控、安全控制黑名单和白名单等。
如何实现动态Gateway网关路由转发?
--> 通过 path 配置拦截请求,通过 Serviceld 到配置中心获取转发的服务列表,Gateway 内部使用 Ribbon 实现本地负载均衡和转发
既然Nginx可以实现网关,为什么还需要使用Gateway框架?
--> nginx偏向网络传输层的网关,Gateway 是 SpringCloud 集成的网关,偏向应用系统服务的网关,可以对 SpringCloud 架构提供更灵活的服务(Gateway的作用)
|-- Config
配置中心:统一管理整个springcloud微服务架构的配置
8.Mybatis 框架
Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sql执行性能,灵活度高。
mybatis底层也是通过JDK动态代理去实现调用sql的功能。
|-- 执行sql的工作原理
1、加载mybatis数据库配置文件
2、加载xml sql文件
3、构造会话工厂sqlsessionfactroy
4、创建sqlsession
5、调用 Executor 执行器,读取sql
6、创建MappedStatement对象,将参数替换到sql中,组装成最终的sql
7、由执行器去执行sql获取数据,将结果封装到ResultHandler中返回,完成整个sql的执行过程
|-- mapper文件中 # 和 $符号的区别
# 在编译时使用 ?占位符进行标记,可以防止sql注;非关键字作为参数时使用,优先使用 # 进行参数传递。
$ 直接把参数拼接到SQL中执行,两边不加 "",使用关键字或字段名作为参数时使用。
9.数据库
|-- 9.1Mysql 数据库
|-- 分库分表
在分布式系统中,请求量大,所有的数据都集中在一个数据库中,单数据库连接有限、处理数据请求的性能容易到达瓶颈,无法满足日益增长的业务需求。所以需要进行分库分表。不同的微服务系统对应不同的数据库,提升整体应用架构的性能。
|-- 索引
就是数据表的目录,能够快速定位查询需要的数据,大大提升查询效率。
|-- 索引为什么能提升查询数据的性能?
使用了B+ 树,非叶子节点只保存索引数据,叶子节点保存了索引数据和业务数据的地址,所以查询的时候可以快速定位到需要查询的业务数据,减少IO次数,减少查询范围,提升查询性能。
|-- sql优化
如何使用索引,以及避免索引失效。
为常作为查询条件、联表查询、排序、分组的字段建立索引。
|-- 高性能索引的策略
1、索引不能是表达式的一部分,也不能是函数的参数
2、前缀索引:当字段里有很长字符串的列,在前几个字符串里加索引,这就是前缀索引
3、联合索引:为多个字段建立一个索引,称之为联合索引,联合索引需要遵从最左前缀原则。在查询时优化器选择最优索引策略,可能只用一个索引,也可能全部索引都用上。
|-- 索引失效的几种情况?
1、like关键字以 % 开头,索引无效,以 % 结尾,索引有效;
2、联合索引不使用第一列,索引失效;
3、or语句没有同时使用索引,索引失效,只有条件两边都使用索引时,索引才有效;
4、在索引字段上使用判空时is null或者is not null 时索引失效,所以索引字段要设置默认值;
5、在索引上使用函数时,索引无效;
6、使用 <> 、!= 运算符时索引失效,改为 key >0 or key <0;
|-- 如何判断sql的执行是否使用了索引
|-- EXPLAIN命令解析
在执行的sql前使用该命令可以分析sql的执行结果
有哪些列?
|-- 重点字段
table 查询了哪些表
id 查询顺序
select_type 查询类型
possible_keys 可能使用到的索引
keys 实际使用的索引,如果为null表示没有使用该索引
rows 查询所需要读取的行数
|-- 集群
|-- 主从模式(读写分离,提高性能,非高可用)
|-- 双主单写模式(读写分离,提高性能,高可用)
|-- 分片模式(了解)
|-- 9.2MongoDB数据库
|-- 基本CRUD操作
|--应用场景
学习了解MongoDB数据库:https://blog.csdn.net/weixin_42039228/article/details/123657641?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522BBE1373E-B7B8-4CF8-85BB-3253DBB73D9C%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=BBE1373E-B7B8-4CF8-85BB-3253DBB73D9C&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-4-123657641-null-null.142^v100^pc_search_result_base1&utm_term=mongodb&spm=1018.2226.3001.4187
10.Redis缓存
|-- 概念
Redis 是Remote Dictionary Server(Redis) 的缩写,是一个使用 C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型的Key-Value数据库,并提供多种语言的API。
它是一种 NoSQL(not-only sql,泛指非关系型数据库)的数据库,可以用作数据库、缓存、消息中间件、分布式锁等。
|-- 基本数据类型
String
Hash
List
Set
Zset
|-- 应用场景
1、缓存
2、分布式锁
3、计数器应用
4、消息中间件
|-- 分布式锁
|-- 什么是分布式锁?
分布式锁,是控制分布式系统不同进程共同访问共享资源的一种锁的实现。秒杀下单、抢红包等等业务场景都需要用到分布式锁,我们项目中经常使用Redis作为分布式锁。
|-- 如何实现分布式锁?
1、使用setNX 结合lua脚本命令去加锁,保证原子性
2、加锁的时候需要有客户端id、过期时间(避免死锁)
3、解锁也是使用lua脚本进行解锁,比较解锁的id是否和加锁的客户端id一致,一致的时候才进行删除锁的操作
4、结合redis 哨兵模式实现高可用
|-- redis与数据库的一致性策略
延缓双删策略
1、先删除缓存
2、更新数据库
3、删除缓存
4、更新缓存
|-- 缓存雪崩、缓存穿透、缓存击穿
缓存雪崩:大量缓存数据同时失效,同时请求数据库,数据库压力过大,数据库被击垮。
解决方案:设置热点数据永久不过期或者随机设置缓存数据的过期时间,避免同时失效。
缓存穿透:大量请求缓存和数据库中不存在的数据,导致数据库压力过大,击垮数据库。
解决方案:缓存穿透我会在接口层增加校验,比如用户鉴权,参数做校验,不合法的校验直接 return。
缓存击穿:缓存击穿,这个跟缓存雪崩有点像,但是又有一点不一样,缓存雪崩是因为大面积的缓存失效,打崩了 DB。而缓存击穿不同的是缓存击穿是指一个 Key 非常热点,在不停地扛着大量的请求,大并发集中对这一个点进行访问,当这个 Key 在失效的瞬间,持续的大并发直接落到了数据库上,就在这个 Key 的点上击穿了缓存。
解决方案:使用互斥锁或者分布式锁来对并发请求进行控制,避免对同一资源的并发读写竞争,另外也可以使用热点数据预加载等机制来提前将热点数据加入缓存,在其失效时快速刷新缓存。
|-- 集群
|-- 主从模式
读写分离,提高性能,非高可用。
|-- 哨兵模式
哨兵集群,缓存集群,用哨兵去监控缓存集群状态,主节点失效时重新选举主节点,保证高性能、高可用。
|-- 分片模式
数据量过大,分片集群(了解)
11.RabbitMQ 消息中间件
|-- 概念
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。
|-- 作用
Q:为什么需要消息队列?
A:从本质上来说是因为互联网的快速发展,业务不断扩张,促使技术架构需要不断的演进
从以前的单体架构到现在的微服务架构,成百上千的服务之间相互调用和依赖。从互联网初期一个服务器上有100 个在线用户已经很了不得,到现在坐拥10亿日活的微信。此时,我们需要有一个「工具」来解耦服务之间的关系、控制资源合理合时的使用以及缓冲流量洪峰等等。因此,消息队列就应运而生了。
它常用来实现:异步处理、服务解耦、流量控制(削峰)
|-- RabbitMQ 三大组件
1、交换器(Exchange):消息代理服务器中用于把消息路由到队列的组件。
2、队列(Queue):用来存储消息的数据结构,位于硬盘或内存中。
3、绑定 (Binding):一套规则,告知交换器消息应该将消息投递给哪个队列。
|-- 三个角色
1、RabbitMQ消息中间件服务
2、生产者
3、消费者
|-- 如何保证消息的可靠性?
消息丢失场景:消息到MQ的过程中搞丢,MQ自己搞丢,MQ到消费过程中搞丢。
生产者到RabbitMQ:事务机制和Confirm机制,注意:事务机制和 Confirm 机制是互斥的,两者不能共存会导致 RabbitMQ 报错。
RabbitMQ自身:持久化、集群、普通模式、镜像模式。
RabbitMQ到消费者:basicAck机制、死信队列、消息补偿机制。
|-- RabbitMQ自身:持久化
Message durability消息持久化
要持久化队列queue的持久化需要在声明时指定durable=True;
这里要注意,队列的名字一定要是Broker中不存在的,不然不能改变此队列的任何属性.
队列和交换机有一个创建时候指定的标志durable,durable的唯一含义就是具有这个标志的队列和交换机会在重启之后重新建立,它不表示说在队列中的消息会在重启后恢复
消息持久化包括3部分
|-- 订阅模型
1、Fanout 模式
2、direct 模式
3、topic 模式 (实际运用中主要使用的模式)
消息分发机制:RabbitMQ的消息模型 https://blog.csdn.net/weixin_54040016/article/details/128848532
|-- 如何避免消息重复消费?
保证消息的幂等性:
1、生成唯一ID绑定消息;
2、消费者消费消息时生成记录;
3、查询消息是否被消费
4、保证消息重复消费结果不变;
5、如果已经消费,不处理该消息。
6、消息持久化,当被消费出现异常时保存再RabbitMQ中持久化,并使用消息补偿机制去处理未处理的消息。
|-- 集群
RabbitMQ 有三种模式:单机模式,普通集群模式,镜像集群模式。
单机模式:就是demo级别的,一般就是你本地启动了玩玩儿的,没人生产用单机模
普通集群模式:意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个。
镜像集群模式:这种模式,才是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,无论元数据(元数据指RabbitMQ的配置数据) 还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。
12.Elasticsearch 全文检索引擎
应用场景:全文检索、日志分析、运维监控、安全分析等。
项目中的应用:商城主页商品搜索,日志存储分析。
|-- 安装使用
|-- 高可用集群
|-- 结合k8s使用教程
在k8s中部署Elasticsearch高可用集群详细教程 https://blog.csdn.net/weixin_53269650/article/details/139632433
13.SkyWalking 全链路追踪工具
SkyWalking 全链路追踪工具-使用入门 https://blog.csdn.net/u011997561/article/details/121292182
14.分布式系统设计与应用
分布式系统架构简单介绍 https://blog.csdn.net/u011997561/article/details/129567370
|-- 为什么使用分布式系统
单体架构系统不能支撑日益增长的业务需求;业务复杂,数据量大,性能要求高。使用分布式系统设计,将单体应用拆分成多个微服务系统,微服务系统之间通过 rest api 通信的方式,分工协作,完成业务处理,便于维护、迭代升级、简化代码、降低系统复杂度。
|-- 分布式系统的架构设计图
设计图:https://i-blog.csdnimg.cn/direct/6c27886b12fc40b1bc6f0f62ecaeeef9.png
业务平台
|-- Nginx
|-- GateWay API 网关
|-- Springcloud 应用层
|-- Springcloud 基础服务(业务中台微服务)
|-- Mysql 数据库
|-- Redis 缓存
|-- RabbitMQ 消息队列
|-- Elasticsearch 全文检索引擎
|-- XXL-JOB 定时任务
业务平台部署监控管理
|-- SkyWalking 全链路追踪工具
|-- git & Docker & K8S 自动化部署、服务编排
|-- 日志收集管理
|-- DevOPS 开发与运维持续集成
|-- 分布式系统需要解决的问题
1、分布式锁
2、分布式事务
3、分布式存储,数据库分库分表
4、分布式缓存
5、分布式消息队列
6、分布式搜索
7、统一配置中心
8、限流、熔断、降级等
9、分布式会话
|-- 分布式锁解决方案
|-- 什么是分布式锁?
分布式锁,是控制分布式系统不同进程共同访问共享资源的一种锁的实现。秒杀下单、抢红包等等业务场景都需要用到分布式锁,我们项目中经常使用Redis作为分布式锁。
|-- 如何实现分布式锁?
1、使用setNX 结合lua脚本命令去加锁,保证原子性
2、加锁的时候需要有客户端id、过期时间(避免死锁)
3、解锁也是使用lua脚本进行解锁,比较解锁的id是否和加锁的客户端id一致,一致的时候才进行删除锁的操作
|-- 分布式事务
问题1、分布式事务产生的背景?
在传统的单体项目中,多个不同的业务逻辑使用的都是同一个数据源,使用的都是同一个事务管理器,所以不会存在事务问题。
在分布式或者微服务架构中,每个服务都有自己的数据源,使用不同事务管理器,如果A服务去调用B服务,B服务执行失败了,A服务的事务和B服务的事务都会回滚,这时候是不存在事务问题的,但是如果A服务B服务执行成功之后出现异常,A服务的事务会回滚,但是B服务的事务不会回滚,此时就存在分布式事务问题。
|-- 分布式事务解决方案
一般用在订单交易的业务场景,使用强一致性的解决方案。
分布式事务解决方案-Seata之TCC模式 https://blog.csdn.net/u011997561/article/details/129244959
|-- Seata TCC 模式
Seata TCC模式是一种分布式事务处理模式,用于解决分布式环境下的一致性问题。它通过将事务分解为三个阶段(Try、Confirm、Cancel)来实现事务的可靠性和一致性。
|-- TCC 工作流程
关键:维护事务状态表,记录每一个阶段事务的状态,来解决异常。
1、Try阶段:尝试执行事务操作,但不做任何持久化处理。
2、Confirm阶段:在Try阶段成功后执行,对Try阶段的操作进行确认,确保事务的最终一致性。
3、Cancel阶段:在Try阶段失败时执行,回滚Try阶段的操作,保证事务的原子性。
|-- Seata TCC模式的基本原理
1、Seata Server 开启全局事务
2、每一个微服务操作一次数据库都会建立一个事务分支,并提交到全局事务管理器中
3、当所有操作执行完毕,并且没有异常时,提交事务,事务全部成功
4、当有一个操作异常时,执行TCC的取消操作,资源回滚,取消所有提交的事务
|-- 网络传输层网关 Nginx
可以实现网络传输层的反向代理,负载均衡,集群。
什么是正向代理?什么是反向代理?
正向代理,指的是通过代理服务器 代理浏览器/客户端去重定向请求访问到目标服务器 的一种代理服务。
正向代理服务的特点是代理服务器 代理的对象是浏览器/客户端,也就是对于目标服务器 来说浏览器/客户端是隐藏的。
反向代理,指的是浏览器/客户端并不知道自己要访问具体哪台目标服务器,只知道去访问代理服务器 ,代理服务器再通过反向代理 +负载均衡实现请求分发到应用服务器的一种代理服务。
反向代理服务的特点是代理服务器 代理的对象是应用服务器,也就是对于浏览器/客户端 来说应用服务器是隐藏的。
|-- 应用层API网关最佳实践解决方案 Gateway
基于SpringCloud Gateway实现分布式系统API网关实践
Spring Cloud Gateway 详解和配置使用(文章较长) https://blog.csdn.net/u011997561/article/details/121160120
|-- 分布式定时任务
XXL-JOB 分布式定时任务调度平台 https://blog.csdn.net/u011997561/article/Sdetails/109298759
|-- 高可用&高性能分布式系统总结
|-- 统一注册中心、配置中心
|-- nginx传输层网关集群、Gateway API应用层网关集群
|-- 应用层集群
|-- 基础服务集群 (业务中台)
|-- Mysql集群、Redis集群、RabbitMQ集群、Elasticsearch集群
|-- git、Docker&k8s 自动化部署、服务编排
|-- SkyWalking全链路追踪工具
|-- 日志收集管理
15.项目经验
|-- 项目(一):华胜汽修商业运营管理平台
|-- 使用技术
SpringBoot、SpringCloud、Mybatis、Redis 、Mysql、RabbitMQ、Maven、git等
|-- 项目描述
该平台是为了满足华胜企业的车辆维修、保养、保险、客户管理及运营等业务而开发的,本项目采用分布式微服务架构,根据业务需求进行领域中心系统划分,业务中台主要由线索中心、客户中心、商品中心、订单中心、活动营销中心、门店中心、客服中心等微服务子系统组成,各子系统间相互独立,并通过各业务系统之间协作处理用户的请求。通过对线索收集跟踪,转化成企业的客户,提供满足客户需求的商品或服务,支持企业进行线上业务流程跟踪管理,对运营数据进行统计分析,满足企业日益发展的业务需求。
|-- 我的职责
1、参与需求分析评审,负责项目架构设计,搭建开发框架;
2、负责管理项目小组的开发工作,制定开发计划、任务拆分、任务跟进等;
3、负责开发核心模块商品中心、订单中心、活动营销中心、客户中心、工单中心等;
4、负责开发事件中心组件,对接内部云客服、精准推荐业务等其他系统;
5、版本迭代需求开发,编写项目技术设计文档,维护线上系统服务等。
|-- 主要业务流程
开始-->收集线索-->转化客户-->客服系统跟进-->客户预约-->客户到店-->车辆维修/保养/保险-->缴费出厂-->客户回访-->精准推荐(根据客户出厂时间,推荐客户返厂消费)-->结束
业务流程图:https://i-blog.csdnimg.cn/direct/866d33211aa7404bb1eb328e2fc5bbc6.png
|-- 项目架构
项目架构图:https://i-blog.csdnimg.cn/direct/97a48c65d768458584b3311fc78bc38d.png
|-- 技术问点
你在该项目中解决了什么难题?
A6:RabbitMQ 异步、解耦接收所有渠道线索;
多线程清洗转化线索数据成为客户数据;
Springcloud 搭建开发分布式服务系统(业务中台);
优化复杂的线索查询统计数据(sql优化);
使用Redis分布式锁解决商品超卖的问题,查询热点数据问题;
使用Seata TCC解决订单下单分布式事务的问题等等;
使用Gateway API网关权限验证、日志、限流、负载均衡等。。。。
|-- 项目(二)沁园设备销售与租赁管理平台
|-- 使用技术
SpringBoot、SpringCloud、Mybatis、Redis 、Mysql、RabbitMQ、Maven、git等
|-- 项目描述
该平台是为了满足沁园企业实现多种净水设备业务的生产、销售、租赁、供应、售后、审批、财务和管理等业务而开发的。本项目采用分布式微服务架构进行开发,业务中台主要由产品中心、订单中心、租赁管理、仓储管理中心、审批中心、活动中心、客户管理、经销商管理中心、维修中心等微服务子系统组成。实现对多种净水设备生产销售租赁管理,对设备整个生命周期的跟踪和服务,整合线上线下销售服务渠道,降低企业生产运营管理成本,汇总统计分析运营业务数据,是一个综合型的销售管理平台。
|-- 我的职责
1、参与需求分析评审,负责项目架构设计,搭建开发环境;
2、负责管理项目小组的开发工作,制定开发计划、拆分任务、代码Review等;
3、负责开发平台服务商品中心、维修中心、活动中心、订单中心、审批中心等;
4、负责对接开发卡券、产品促销活动、转介绍等运营活动业务需求;
5、解决系统测试问题,发布项目服务,跟踪处理系统线上问题。
|-- 主要业务流程
开始-->建立产品分类-->定义产品(物料、配件组成)-->生产发布商品-->客户下单(购买/租赁)-->订单审批-->经销商发货-->客户收货-->售后维修-->客户发起工单-->工单审批指派-->工单处理结果记录-->服务评价-->财务对账-->收入支出统计-->结束
业务流程图:https://i-blog.csdnimg.cn/direct/d3b492d887e2471896418a69cba536c1.png
|-- 项目架构
项目架构图:https://i-blog.csdnimg.cn/direct/7147f90efc1740139ceb1f02bc57c5c2.png
|-- 技术问点
你在该项目中解决了什么难题?
多线程处理数据同步、
使用springcloud搭建分布式服务系统、
使用rabbitmq实现异步解耦对接其他内部系统、
使用redis缓存热点数据,提高系统性能、
使用mysql作为数据库、进行sql的优化、
使用springcloud gateway作为服务网关、
使用分布式锁解决系统资源的同步的问题等。。。
|-- 项目(三)BTL车展管理运营平台
|-- 使用技术
SpringBoot、SpringCloud、Mybatis、Redis 、Mysql、RabbitMQ、Maven、git等
|-- 项目描述
该系统是为东风日产品牌营销工作开展而开发的服务平台,对车展和公司品牌运营进行统一的规划和管理,支持企业进行发布需求方案申报与审批,规划管理车展站点线路, 进行车展所需物资配置,制定年度车展计划,进度管理,发布车展销售优惠活动,跟进服务客户,解决客户需求,完善品牌专营店管理,供应商管理,提升品牌影响力,及促进车辆销售,达到增强企业营收效益的目的。
|-- 我的职责
1、参与需求分析评审、编写系统设计文档
2、开发车展计划申报、审批、车展站点路线管理、发布优惠活动、客户下单、专营店管理等功能模块
3、开发客户留资跟踪、客户评价反馈等功能
4、接口对接测试联调
|-- 主要业务流程
开始-->申请车展计划-->计划审批-->发布车展站点、路线-->指派供应商、门店、人员配置-->管理车展物资供应进度、发布推广车展活动-->品牌介绍、客户留资、现场下单购买-->留资线索跟进、专营店订单交付、车展活动评价-->完成车展计划/财务对账/收入支出/统计-->结束
业务流程图:https://i-blog.csdnimg.cn/direct/34bfa12876a44c9ab625071d35e0141b.png
|-- 项目架构
项目架构图:https://i-blog.csdnimg.cn/direct/e947ac4fa0b6400288e3e6cfb22d5a6e.png
|-- 技术问点
你在该项目中解决了什么难题?
编写系统设计、搭建系统框架;
负责车展计划、站点线路、订单、专营店管理、进度管理等功能模块设计开发;
负责和产品人员沟通完成客户留资跟踪、待办事项管理、广告管理等功能开发等。。。
使用springcloud、redis、mysql进行开发;
使用rabbitMQ异步通知对接内部业务系统等等。。。
|-- 项目(四)美的置业物联网管理平台
|-- 使用技术
SpringBoot、SpringCloud、Mybatis、Redis 、Mysql、PulsarMQ、Maven、git等
|-- 项目描述
该平台是一个基于地产社区行业的社区管理平台,集成了智慧人行、智慧停车、视频安防、内容运营、设备管理、IDC大屏数据统计、连接器升级等业务系统的综合型平台,为便捷智能社区生活提供有效稳定支撑能力,可以进行集成式的空间管理,降低地产社区管理成本,提高社区信息流通效率,增强企业的社区管理运营水平。
|-- 我的职责
1、参与业务需求评审,负责人行、智慧停车业务系统分析设计;
2、负责智慧人行业务小组的开发任务管理,跟踪推进开发任务进度;
3、负责开发社区空间服务、智慧门禁、智慧停车、人脸管理业务模块;
4、负责开发内容运营业务,社区资讯、社区活动、广告管理等功能;
5、编写和维护规范文档,维护线上业务系统稳定,解决系统出现的问题。
|-- 主要业务流程
智慧人行:开始-->初始化地产项目楼栋单元停车场数据、业主数据-->门禁、停车场、电梯设备连接到IOT物联网平台-->录入绑定业主、通行卡、人脸信息-->业主通行从设备传送开门请求到IOT平台-->校验业主通行权限-->发送开门请求到设备开门-->结束
智慧停车:开始-->设备连接到IOT平台-->车辆进场-->判断是月租车辆还是临时车辆-->出场计算停车时长-->调用智慧停车业务系统服务计算停车费-->生成支付二维码-->通过IOT平台下发二维码到停车门禁设备-->用户支付完成-->设备反馈信息到智慧停车系统-->下发开启车辆门禁闸指令放行车辆-->结束
业务流程图:https://i-blog.csdnimg.cn/direct/9df2b3fc0333444dbce840f78bacc083.png
|-- 项目架构
项目架构图:https://i-blog.csdnimg.cn/direct/16f25a42baec47e28ba617c9af7b6fc3.png
|-- 技术问点
你在该项目中解决了什么难题?
多线程数据同步;
处理并发开门问题;
分析系统业务,设计搭建框架;
管理开发小组任务,代码review;
PulsarMQ消息异步处理设备上下线问题;
异步通知设备信息;
springcloud搭建分布式系统平台。。。等等
<完>