赞
踩
原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。
一个操作是不可中断的,要么全部执行成功要么全部执行失败
例如张三给李四转账100元。. 事务要做的是从张三账户上减掉100元,李四账户上加上100元。. 一致性的含义是其他事务要么看到张三还没有给李四转账的状态,要么张三已经成功转账给李四的状态,而对于张三少了100元,李四还没加上100元这个中间状态是不可见的。. 要么转账操作全部成功,要么全部失败,这是原子性。.
数据库对多事务并发执行的一个控制,描述了多个事务并发执行时,事务与事务之间操作数据的可见性。
持久性是指事务一旦提交,它对数据库的改变就应该是永久性的,接下来的其他操作或故障不应该对本次事务的修改有任何影响。
未提交读(Read uncommitted)
已提交读(Read committed )
可重复读(Repeatable read),这是mysql默认的隔离级别
串行化 (Serializable)
读未提交
MySQL 事务隔离其实是依靠锁来实现的,加锁自然会带来性能的损失。而读未提交隔离级别是不加锁的,所以它的性能是最好的,没有加锁、解锁带来的性能开销。但有利就有弊,这基本上就相当于裸奔啊,所以它连脏读的问题都没办法解决。
读提交
既然读未提交没办法解决脏数据问题,那么就有了读提交。读提交就是一个事务只能读到其他事务已经提交过的数据,也就是其他事务调用 commit 命令之后的数据。那脏数据问题迎刃而解了。
读提交解决了脏读的问题,但是无法做到可重复读,也没办法解决幻读。
可重复读
可重复是对比不可重复而言的,上面说不可重复读是指同一事物不同时刻读到的数据值可能不一致。而可重复读是指,事务不会读到其他事务对已有数据的修改,及时其他事务已提交,也就是说,事务开始时读到的已有数据是什么,在事务提交前的任意时刻,这些数据的值都是一样的。但是,对于其他事务新插入的数据是可以读到的,这也就引发了幻读问题。
串行化
串行化是4种事务隔离级别中隔离效果最好的,解决了脏读、可重复读、幻读的问题,但是效果最差,它将事务的执行变为顺序执行,与其他三个隔离级别相比,它就相当于单线程,后一个事务的执行必须等待前一个事务结束。
1、在事务A执行过程中,事务A对数据资源进行了修改,事务B读取了事务A修改后的数据。
2、由于某些原因,事务A并没有完成提交,发生了RollBack操作,则事务B读取的数据就是脏数据。
这种读取到另一个事务未提交的数据的现象就是脏读(Dirty Read)。
事务B读取了两次数据资源,在这两次读取的过程中事务A修改了数据,导致事务B在这两次读取出来的数据不一致。
这种在同一个事务中,前后两次读取的数据不一致的现象就是不可重复读(Nonrepeatable Read)。
事务B前后两次读取同一个范围的数据,在事务B两次读取的过程中事务A新增了数据,导致事务B后一次读取到前一次查询没有看到的行。
幻读和不可重复读有些类似,但是幻读强调的是集合的增减,而不是单条数据的更新。
以.java文件结尾的称作源代码文件,它经过编译器编译之后形成了.class文件(字节码文件),然后由JVM中的类加载器进行加载各个类的字节码文件,加载完毕之后,由JVM执行引擎执行.在整个执行的过程中,JVM会用一段空间来存储期间所用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。
(1)引用计数法
给对象添加一引用计数器,被引用一次计数器值就加 1;当引用失效时,计数器值就减 1;计数器为 0 时,对象就是不可能再被使用的,简单高效,缺点是无法解决对象之间相互循环引用的问题。
(2)可达性分析算法
通过一系列的称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的。此算法解决了上述循环引用的问题。
1.效率问题,标记和清除两个过程的效率都不高;
2.空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
为了解决效率问题,一种称为“复制”(Copying)的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
复制算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。更关键的是,如果不想浪费 50% 的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都 100% 存活的极端情况,所以在老年代一般不能直接选用这种算法。
分别是corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。下面会对这7个参数一一解释。
一、corePoolSize 线程池核心线程大小
线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。任务提交到线程池后,首先会检查当前线程数是否达到了corePoolSize,如果没有达到的话,则会创建一个新线程来处理这个任务。
二、maximumPoolSize 线程池最大线程数量
当前线程数达到corePoolSize后,如果继续有任务被提交到线程池,会将任务缓存到工作队列(后面会介绍)中。如果队列也已满,则会去创建一个新线程来出来这个处理。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。
三、keepAliveTime 空闲线程存活时间
一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定
四、unit 空闲线程存活时间单位
keepAliveTime的计量单位
五、workQueue 工作队列
新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:
①ArrayBlockingQueue
基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
②LinkedBlockingQuene
基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而基本不会去创建新线程直到maxPoolSize(很难达到Interger.MAX这个数),因此使用该工作队列时,参数maxPoolSize其实是不起作用的。
③SynchronousQuene
一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。
④PriorityBlockingQueue
具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
六、threadFactory 线程工厂
创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等
七、handler 拒绝策略
当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,该如何处理呢。这里的拒绝策略,就是解决这个问题的,jdk中提供了4中拒绝策略:
IO和IO的主要区别
下表总结了Java IO和NIO之间的主要区别:
IO | NIO |
面向流 | 面向缓冲 |
阻塞IO | 非阻塞IO |
无 | 选择器 |
AIO 是彻底的异步通信。
NIO 是同步非阻塞通信。
在目标对象(target object)的某些方法(jointpoint)添加不同种类的操作(通知、增强操处理),最后通过某些方法(weaving、织入操作)实现一个新的代理目标对象。
AOP使用场景
AOP用来封装横切关注点,具体可以在下面的场景中使用:
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging 调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务
top, uptime,w,vmstat
Linux查看日志的命令有多种: tail、cat、tac、head、echo等
分布式系统是一组计算机系统一起工作,在终端用户看来,就像一台计算机在工作一样。
这组一起工作的计算机,拥有共享的状态,他们同时运行,独立机器的故障不会影响整个系统的正常运行。
考虑方面:
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手。
三次握手过程的示意图如下:
SYN_SENT
状态,等待服务器端确认。SYN_RCVD
状态。ESTABLISHED
状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
四次挥手过程的示意图如下:
DoS(Denial of Service,拒绝服务攻击),它的原理很简单,就是用我们手里的机器去给服务器发请求,如果我们手头的服务器各方面性能都比服务器的主机的性能好,那么当我们发送大量请求给服务器,占用服务器的资源,导致服务器没有能力去处理其他用户请求。
DDoS(Distributed Denial of Service,分布式拒绝服务),它是DoS家族里很难防范的一种攻击方式,攻击者首先控制大量肉鸡,然后向目标服务器发送海量请求,导致目标服务器不可用
DRDoS
通过上文介绍,DDos攻击需要获取大量的肉鸡,但是获取肉鸡也越来越困难了,那目前还有没有不用控制肉鸡还能大量攻击的呢?DRDoS((Distributed Reflection Denial of Service,分布式反射拒绝服务),攻击者将不是将请求直接发送给被攻击者,而是发送给一个第三方,通过第三方中转到被攻击者,这就是"Reflection"的体现。
粉红色的是受检查的异常(checked exceptions),其必须被 try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.受检查的异常必须在编译时被捕捉处理,命名为 CHecked Exception 是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守.
绿色的异常是运行时异常(runtime exceptions),需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除...
而声明为Error的,则属于严重错误,需要根据业务信息进行特殊处理,Error不需要捕捉。
情况二: 使用了 System.exit(int) 退出程序
情况三:程序所在的线程死亡
1、不管有没有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
按程序顺序运行,如果try中有异常,会执行catch中的代码块,有异常与否都会执行finally中的代码;最终返回。
数值类型
byte类型:值为8位的有符号二进制补码整数,默认值为0;
short类型:值为16位的有符号二进制补码整数,默认值为0;
int 类型:值为32位的有符号二进制补码整数,默认值为0;
long类型:值为64位的有符号二进制补码整数,默认值为0;
char类型:值为16位的无符号二进制补码整数,默认值为Unicode的null码点(’\u0000’);
float类型:值为单精度浮点指数集合中的元素,或是单精度扩展指数集合中的元素,默认值为正数0;
double类:值为双精度浮点指数集合中的元素,或是双精度扩展指数集合中的元素,默认值为正数0;
引用类型
Java虚拟机的引用类型包括三种:
类类型(class type):指向动态创建的类实例;
数组类型(array type):指向数值实例;
接口类型(interface type):指向实现了某个接口的类实例或数组实例;
在引用类型中还存在一个特殊的值:null,当一个引用不指向任何对象时,它的值就是null,一个为null的引用可以转换为任意的引用类型,null也就是引用类型的默认值;
File -- 文件类
RandomAccessFile -- 随机存储文件类
InputStream -- 字节输入流
OutputStream -- 字节输出流
Reader -- 字符输入流
Writer -- 字符输出流
1)线程安全
StringBuffer:线程安全,StringBuilder:线程不安全
因为 StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有。
(2)缓冲区
StringBuilder的性能要远大于StringBuffer
(4)作用领域
什么是反射
反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
3、SpringBoot、Spring MVC 和 Spring 有什么区别?
1、 Spring
Spring最重要的特征是依赖注入。所有 SpringModules 不是依赖注入就是 IOC 控制反转。
当我们恰当的使用 DI 或者是 IOC 的时候,我们可以开发松耦合应用。松耦合应用的单元测试可以很容易的进行。
2、 Spring MVC
Spring MVC 提供了一种分离式的方法来开发 Web 应用。通过运用像 DispatcherServelet,MoudlAndView 和 ViewResolver 等一些简单的概念,开发 Web 应用将会变的非常简单。
3、 SpringBoot
Spring 和 SpringMVC 的问题在于需要配置大量的参数。
SpringBoot 通过一个自动配置和启动的项来目解决这个问题。为了更快的构建产品就绪应用程序,SpringBoot 提供了一些非功能性特征。
4、什么是SpringBoot
1、 用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置(properties或yml文件)
2、 创建独立的spring引用程序 main方法运行
3、 嵌入的Tomcat 无需部署war文件
4、 简化maven配置
5、开启 SpringBoot 特性有哪几种方式?
1、 继承spring-boot-starter-parent项目
2、 导入spring-boot-dependencies项目依赖
6、什么是YAML?
YAML是一种人类可读的数据序列化语言。它通常用于配置文件。 与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。
7、什么是Spring Profiles?
Spring Profiles允许用户根据配置文件(dev,test,prod等)来注册bean。因此,当应用程序在开发中运行时,只有某些bean可以加载,而在PRODUCTION中,某些其他bean可以加载。假设我们的要求是Swagger文档仅适用于QA环境,并且禁用所有其他文档。这可以使用配置文件来完成。SpringBoot使得使用配置文件非常简单。
8、如何在 SpringBoot 中添加通用的 JS 代码?
在源文件夹下,创建一个名为 static 的文件夹。然后,你可以把你的静态的内容放在这里面。
例如,myapp.js 的路径是 resources\static\js\myapp.js
你可以参考它在 jsp 中的使用方法:
错误:HAL browser gives me unauthorized error - Full authenticaition is required to access this resource.
该如何来修复这个错误呢?
两种方法:
方法 1:关闭安全验证
application.properties
management.security.enabled:FALSE
方法二:在日志中搜索密码并传递至请求标头中
9、SpringBoot 有哪几种读取配置的方式?
SpringBoot 可以通过 @PropertySource,@Value,@Environment, @ConfigurationProperties 来绑定变量。
10、SpringBoot 是否可以使用 XML 配置 ?
SpringBoot 推荐使用 Java 配置而非 XML 配置,但是 SpringBoot 中也可以使用 XML 配置,通过 @ImportResource 注解可以引入一个 XML 配置。
11、SpringBoot自动配置的原理是什么?
SpringBoot启动的时候通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中所有的自动配置类,并对其进行加载,而这些自动配置类的类名都是以AutoConfiguration结尾来命名的,它实际上就是一个javaConfig形式的Spring容器配置类,它们都有一个@EnableConfigurationPerperties的注解,通过这个注解启动XXXProperties命名的类去加载全局配置中的属性,如server.port,而XXXProperties通过@ConfigurationProperties注解将全局配置文件中的属性与自己的属性进行绑定。
12、SpringBoot 配置加载顺序?
1、 properties文件 2、YAML文件 3、系统环境变量 4、命令行参数
13、spring boot初始化环境变量流程?
1、 调用prepareEnvironment方法去设置环境变量
2、 接下来有三个方法getOrCreateEnvironment,configureEnvironment,environmentPrepared
3、 getOrCreateEnvironment去初始化系统环境变量
4、 configureEnvironment去初始化命令行参数
5、 environmentPrepared当广播到来的时候调用onApplicationEnvironmentPreparedEvent方法去使用postProcessEnvironment方法load yml和properties变量
14、运行 SpringBoot 有哪几种方式?
1、 打包用命令或者者放到容器中运行
2、 用 Maven/ Gradle 插件运行
3、 直接执行 main 方法运行
15、SpringBoot 中如何解决跨域问题 ?
跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,无法发送其他类型的请求,在 RESTful 风格的应用中,就显得非常鸡肋,因此我们推荐在后端通过 (CORS,Cross-origin resource sharing) 来解决跨域问题。这种解决方案并非 SpringBoot 特有的,在传统的 SSM 框架中,就可以通过 CORS 来解决跨域问题,只不过之前我们是在 XML 文件中配置 CORS ,现在可以通过实现WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .maxAge(3600); }
}
16、SpringBoot如何配置log4j?
在引用log4j之前,需要先排除项目创建时候带的日志,因为那个是Logback,然后再引入log4j的依赖,引入依赖之后,去src/main/resources目录下的log4j-spring.properties配置文件,就可以开始对应用的日志进行配置使用。
17、SpringBoot运行项目的几种方式?
打包用命令或者放到容器中运行
1、 打成jar包,使用java -jar xxx.jar运行
2、 打成war包,放到tomcat里面运行
直接用maven插件运行 maven spring-boot:run
直接执行main方法运行
18、什么是JavaConfig?
Spring JavaConfig是Spring社区的产品,它提供了配置Spring IoC容器的纯Java方法。因此它有助于避免使用XML配置。使用JavaConfig的优点在于:
面向对象的配置。由于配置被定义为JavaConfig中的类,因此用户可以充分利用Java中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean方法等。
减少或消除XML配置。基于依赖注入原则的外化配置的好处已被证明。但是,许多开发人员不希望在XML和Java之间来回切换。
JavaConfig为开发人员提供了一种纯Java方法来配置与XML配置概念相似的Spring容器。
从技术角度来讲,只使用JavaConfig配置类来配置容器是可行的,但实际上很多人认为将JavaConfig与XML混合匹配是理想的。
类型安全和重构友好。JavaConfig提供了一种类型安全的方法来配置Spring容器。由于Java 5.0对泛型的支持,现在可以按类型而不是按名称检索bean,不需要任何强制转换或基于字符串的查找
19、运行 SpringBoot 有哪几种方式?
1、 打包用命令或者放到容器中运行
2、 用 Maven/ Gradle 插件运行
3、 直接执行 main 方法运行
20、SpringBoot 常用的 Starter 有哪些?
1、 spring-boot-starter-web :提供 Spring MVC + 内嵌的 Tomcat 。
2、 spring-boot-starter-data-jpa :提供 Spring JPA + Hibernate 。
3、 spring-boot-starter-data-Redis :提供 Redis 。
4、 mybatis-spring-boot-starter :提供 MyBatis 。
21、在 Spring Initializer 中,如何改变一个项目的包名字?
好消息是你可以定制它。点击链接“转到完整版本”。你可以配置你想要修改的包名称!
22、SpringBoot 的配置文件有哪几种格式?它们有什么区别?
.properties 和 .yml,它们的区别主要是书写格式不同。
properties
app.user.name = javastack
yml
app: user: name: javastack
23、什么是 Swagger?你用 SpringBoot 实现了它吗?
Swagger 广泛用于可视化 API,使用 Swagger UI 为前端开发人员提供在线沙箱。Swagger 是用于生成 RESTful Web 服务的可视化表示的工具,规范和完整框架实现。它使文档能够以与服务器相同的速度更新。当通过 Swagger 正确定义时,消费者可以使用最少量的实现逻辑来理解远程服务并与其进行交互。因此,Swagger消除了调用服务时的猜测。
24、spring boot 核心配置文件是什么?bootstrap、properties 和 application、properties 有何区别 ?
单纯做 SpringBoot 开发,可能不太容易遇到 bootstrap、properties 配置文件,但是在结合 Spring Cloud 时,这个配置就会经常遇到了,特别是在需要加载一些远程配置文件的时侯。
spring boot 核心的两个配置文件:
bootstrap (、 yml 或者 、 properties):boostrap 由父 ApplicationContext 加载的,比 applicaton 优先加载,配置在应用程序上下文的引导阶段生效。一般来说我们在 Spring Cloud 配置就会使用这个文件。且 boostrap 里面的属性不能被覆盖;
application (、 yml 或者 、 properties): 由ApplicatonContext 加载,用于 spring boot 项目的自动化配置。
25、什么是Spring Initializer?
这个问题并不难,但面试官总是以此测试候选人的专业知识。
Spring Initializer是一个网络应用程序,它可以生成一个SpringBoot项目,包含快速启动所需的一切。和往常一样,我们需要一个好的项目框架;它有助于你正确创建项目结构/框架。
26、SpringBoot Starter 的工作原理是什么?
SpringBoot 在启动的时候会干这几件事情:
1、 SpringBoot 在启动时会去依赖的 Starter 包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的 Jar 包去扫描项目所依赖的 Jar 包。
2、 根据 spring.factories 配置加载 AutoConfigure 类
3、 根据 @Conditional 注解的条件,进行自动配置并将 Bean 注入 Spring Context
总结一下,其实就是 SpringBoot 在启动的时候,按照约定去读取 SpringBoot Starter 的配置信息,再根据配置信息对资源进行初始化,并注入到 Spring 容器中。这样 SpringBoot 启动完毕后,就已经准备好了一切资源,使用过程中直接注入对应 Bean 资源即可。
采用AMQP高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦。
2、为什么要使用rabbitmq?
答:
1、在分布式系统下具备异步,削峰,负载均衡等一系列高级功能;
2、拥有持久化的机制,进程消息,队列中的信息也可以保存下来。
3、实现消费者和生产者之间的解耦。
4、对于高并发场景下,利用消息队列可以使得同步访问变为串行访问达到一定量的限流,利于数据库的操作。
5、可以使用消息队列达到异步下单的效果,排队中,后台进行逻辑下单。
3、使用rabbitmq的场景。
答:
1、服务间异步通信
2、顺序消费
3、定时任务
4、请求削峰
4、如何确保消息正确地发送至RabbitMQ?如何确保消息接收方消费了消息?
答:
发送方确认模式
1.将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。
2.一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一 ID)。
3.如果 RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack(notacknowledged,未确认)消息。发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
答:
1、服务间高度解耦
2、异步通信性能高
3、流量削峰
RabbitMQ的工作模式。
答:
一.simple模式(即最简单的收发模式)
消息产生消息,将消息放入队列
消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失,这里可以设置成手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出)。
二.work工作模式(资源的竞争)
3.消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。
4.C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患:高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使用)。
三.publish/subscribe发布订阅(共享资源)
5.每个消费者监听自己的队列;
6.生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。
四.routing路由模式
8. 消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息;
9.根据业务功能定义路由字符串;
10.从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中。
11.业务场景:error通知;EXCEPTION;错误通知的功能;传统意义的错误通知;客户通知;利用key路由,可以将程序中的错误封装成消息传入到消息队列中,开发者可以自定义消费者,实时接收错误; 五.topic 主题模式(路由模式的一种)
12. 星号井号代表通配符
13.星号代表多个单词,井号代表一个单词
14.路由功能添加模糊匹配
15.消息产生者产生消息,把消息交给交换机
16.交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费(在我的理解看来就是routing查询的一种模糊匹配,就类似sql的模糊查询方式)
Kafka是一种高吞吐量、分布式、基于发布/订阅的消息系统,最初由LinkedIn公司开发,使用Scala语言编写,目前是Apache的开源项目。
broker: Kafka服务器,负责消息存储和转发
topic:消息类别,Kafka按照topic来分类消息
partition: topic的分区,一个topic可以包含多个partition, topic 消息保存在各个partition上4. offset:消息在日志中的位置,可以理解是消息在partition上的偏移量,也是代表该消息的唯一序号
Producer:消息生产者
Consumer:消息消费者
Consumer Group:消费者分组,每个Consumer必须属于一个group
Zookeeper:保存着集群 broker、 topic、 partition等meta 数据;另外,还负责broker故障发现, partition leader选举,负载均衡等功能
缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏进行慢慢处理。
解耦和扩展性:项目开始的时候,并不能确定具体需求。消息队列可以作为一个接口层,解耦重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能力。
冗余:可以采用一对多的方式,一个生产者发布消息,可以被多个订阅topic的服务消费到,供多个毫无关联的业务使用。
健壮性:消息队列可以堆积请求,所以消费端业务即使短时间死掉,也不会影响主要业务的正常进行。
异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
ISR:In-Sync Replicas 副本同步队列
AR:Assigned Replicas 所有副本
ISR是由leader维护,follower从leader同步数据有一些延迟(包括延迟时间replica.lag.time.max.ms和延迟条数replica.lag.max.messages两个维度, 当前最新的版本0.10.x中只支持replica.lag.time.max.ms这个维度),任意一个超过阈值都会把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也会先存放在OSR中。AR=ISR+OSR。
broker 是消息的代理,Producers往Brokers里面的指定Topic中写消息,Consumers从Brokers里面拉取指定Topic的消息,然后进行业务处理,broker在中间起到一个代理保存消息的中转站。
zookeeper 是一个分布式的协调组件,早期版本的kafka用zk做meta信息存储,consumer的消费状态,group的管理以及 offset的值。考虑到zk本身的一些因素以及整个架构较大概率存在单点问题,新版本中逐渐弱化了zookeeper的作用。新的consumer使用了kafka内部的group coordination协议,也减少了对zookeeper的依赖,但是broker依然依赖于ZK,zookeeper 在kafka中还用来选举controller 和 检测broker是否存活等等。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。