java面试常见八股文整理

java面试常见八股文整理

沟通表达能力

1. 清晰,流畅的介绍自己,教育,工作经历,优势及爱好。

2. 自己项目系统组成,每个分系统/应用作用

3. 负责工作职责,任务完成情况,清楚的表述负责业务

4. 离职原因,目前工位环境是否匹配。

5. 未来职业规划,积极向上有追求。

Java基础

1.常用的Java集合有哪些,有什么应用场景

Java集合可以分为Collection和Map两种体系
Collection接口:单列数据,定义存取一组对象的方法的集合
LIst:元素有序、可重复的集合
Set:元素无序、不可重复的集合
Map接口:双列数据,保存具有映射关系“Key-value对”的集合

2. Java线程创建方式有几种,分别是什么,有哪些适用场景

  1. 继承Thread类创建线程类
    (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
    (2)创建Thread子类的实例,即创建了线程对象。
    (3)调用线程对象的start()方法来启动该线程。

  2. 通过Runnable接口创建线程类
    (1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
    (2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
    (3)调用线程对象的start()方法来启动该线程。

  3. 覆写Callable接口实现多线程(JDK1.5)

  4. 通过线程池启动多线程
    (1)使用Executors类中的newFixedThreadPool(int num)方法创建一个线程数量为num的线程池。
    (2)调用线程池中的execute()方法执行由实现Runnable接口创建的线程;调用submit()方法执行由实现Callable接口创建的线程。
    (3)调用线程池中的shutdown()方法关闭线程池。 其中
    Callable和线程池是JDK5之后新增的,与使用Runnable相比,Callable功能更强大些

相比run()方法,可以有返回值
方法可以抛出异常
支持泛型的返回值
需要借助FutureTask类,比如获取返回结果

3. Java线程start方法和run方法的区别

  1. start方法启动了一个新的线程,而run方法不能启动一个新线程,还是在main线程下运行,程序依然是主线程一个线程在运行。
  2. 调用start方法可以启动线程,而run方法只是thread的一个普通方法还是在主线程中执行。
  3. 通过start()方法来启动的新线程,处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行相应线程的run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。start()不能被重复调用。而run方法能被重复调用,因为它就是一个普通的成员方法。
  4. start方法在执行线程体中代码时,在不执行完的情况下可以进行线程切换,而run方法不能,run方法只能进行顺序执行。

4. 多线程编程下,怎么解决线程的数据安全问题?

  1. 如果线程存在竞争临界资源,多线程访问下添加同步代码块synchronized解决,或者分布式排他锁进行临界资源控制。
  2. 在分布式多线程环境下,线程的数据安全尽量不要产生连接资源,使用线程本地化ThreadLocal实现线程资源隔离。

5.SpringIOC依赖注入怎么理解,spring有几种方式

  1. 属性注入,setter
  2. 构建pojo实体类和有参构造方法
  3. 工厂方法注入 (此种用的不多,扩展)

6.SQL注入是怎么产生的,怎么避免?

SQL 注入就是在用户输入的字符串中加入 SQL 语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的 SQL
语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。 SQL 注入的原理主要有以下 4 点:

  1. 恶意拼接查询 我们知道,SQL 语句可以查询、插入、更新和删除数据,且使用分号来分隔不同的命令。例如:
    SELECT * FROM users WHERE user_id = $user_id
    其中,user_id 是传入的参数,如果传入的参数值为“1234;DELETE FROM users”,那么最终的查询语句会变为:
    SELECT * FROM users WHERE user_id = 1234; DELETE FROM users
    如果以上语句执行,则会删除 users 表中的所有数据。
  2. 利用注释执行非法命令。
    SQL 语句中可以插入注释。例如:
    SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version=$version
    如果 version 包含了恶意的字符串’-1’ OR 3 AND SLEEP(500)–,那么最终查询语句会变为:
    SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version='-1' OR 3 AND SLEEP(500)--
    以上恶意查询只是想耗尽系统资源,SLEEP(500) 将导致 SQL 语句一直运行。如果其中添加了修改、删除数据的恶意指令,那么将会造成更大的破坏。
  3. 传入非法参数
  4. 添加额外条件在 SQL
    语句中添加一些额外条件,以此来改变执行行为。条件一般为真值表达式。例如: UPDATE users SET userpass='$userpass' WHERE user_id=$user_id;
    如果 user_id 被传入恶意的字符串“1234 OR TRUE”,那么最终的 SQL 语句会变为:
    UPDATE users SET userpass= '123456' WHERE user_id=1234 OR TRUE;
    这将更改所有用户的密码。
    避免SQL注入 对于 SQL 注入,我们可以采取适当的预防措施来保护数据安全。下面是避免 SQL 注入的一些方法。
    1. 过滤输入内容,校验字符串
    2. 参数化查询
      参数化查询目前被视作是预防 SQL 注入攻击最有效的方法。参数化查询是指在设计与数据库连接并访问数据时,在需要填入数值或数据的地方,使用参数(Parameter)来给值。
      MySQL 的参数格式是以“?”字符加上参数名称而成,如下所示:
      UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4
      在使用参数化查询的情况下,数据库服务器不会将参数的内容视为 SQL 语句的一部分来进行处理,而是在数据库完成 SQL 语句的编译之后,才套用参数运行。因此就算参数中含有破坏性的指令,也不会被数据库所运行。
    3. 安全测试、安全审计
      除了开发规范,还需要合适的工具来确保代码的安全。我们应该在开发过程中应对代码进行审查,在测试环节使用工具进行扫描,上线后定期扫描安全漏洞。通过多个环节的检查,一般是可以避免SQL 注入的。
      有些人认为存储过程可以避免 SQL注入,存储过程在传统行业里用得比较多,对于权限的控制是有一定用处的,但如果存储过程用到了动态查询,拼接 SQL,一样会存在安全隐患。

下面是在开发过程中可以避免 SQL 注入的一些方法。

  1. 避免使用动态SQL
    避免将用户的输入数据直接放入 SQL 语句中,最好使用准备好的语句和参数化查询,这样更安全。
  2. 不要将敏感数据保留在纯文本中
    加密存储在数据库中的私有/机密数据,这样可以提供了另一级保护,以防攻击者成功地排出敏感数据。
  3. 限制数据库权限和特权
    将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。
  4. 避免直接向用户显示数据库错误
    攻击者可以使用这些错误消息来获取有关数据库的信息。

7. MyBatis中#占位符和$占位符有什么区别?

关于#{}和${}的区别

  1. #{}是预编译处理,$ {}是字符串替换。
  2. MyBatis在处理#{}时,会将SQL中的#{}替换为?号,使用PreparedStatement的set方法来赋值;MyBatis在处理$ { } 时,就是把 ${ } 替换成变量的值。
  3. 使用 #{} 可以有效的防止SQL注入,提高系统安全性。 预编译的机制。预编译是提前对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。我们知道,SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作。而预编译机制则可以很好的防止SQL注入。

业务场景: select * from user where id= "1";
上述 sql 中,我们希望对应的id可以变化,根据不同的id查询出不同的学生,在 Mapper.xml文件中使用如下的 sql 可以实现动态传递参数 id:

  1. 关于#的使用
    select * from user where id= #{id};
    当传来参数id=2的时候,解析为:
    select * from user where id= ?;

  2. 关于$的使用
    select * from user where id= ${id};
    当传来参数id=2的时候,解析为:
    select * from user where id = "2";
    小结: ${ } 变量的替换阶段是在动态 SQL 解析阶段,而 #{ }变量的替换是在 DBMS 中。

8.springboot和springcloud区别。 boot里的starter是什么,@Configuration作用

springboot和springcloud的区别主要是:

  1. 作用不同:前者的作用是为了提供一个默认配置,从而简化配置过程;后者的作用是为了给微服务提供一个综合管理框架。
  2. 使用方式不同:springboot可以单独使用;springcloud必须在springboot使用的前提下才能使用。SpringBoot专注于快速方便的开发单个个体微服务,SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并且管理起来,为各个服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、精选决策、分布式会话等集成服务。
    springboot和springcloud都是从spring生态圈中衍生出来的软件开发框架,但是二者的创作初衷是完全不同的,springboot的设计目的是为了在微服务开发过程中可以简化配置文件,提高工作效率,而springcloud的设计目的是为了管理同一项目中的各项微服务,因此二者是完全不同的两个软件开发框架。

9.常用设计模式,解决什么问题:工厂、策略、责任链

一、工厂模式最主要解决的问题就是创建者和调用者的耦合,那么代码层面其实就是取消对new的使用。
工厂模式可以分为:简单工厂模式、工厂方法模式和抽象工厂模式。

  1. 简单工厂模式又叫 静态方法模式,因为工厂类中定义了一个静态方法用于创建对象。简单工厂让使用者不用知道具体的参数就可以创建出所需的 ”产品“类,即使用者可以直接消费产品而不需要知道产品的具体生产细节。
    工厂类负责创建的对象比较少:由于创建的对象比较少,不会造成工厂方法中业务逻辑过于复杂。
    客户端只需知道传入工厂类静态方法的参数,而不需要关心创建对象的细节。

  2. 工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫多态工厂(Polymorphic Factory)模式,它属于类创建型模式。
    在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象, 这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

  3. 抽象工厂模式(Abstract Factory Pattern),提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
    在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。
    但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

二、策略模式可以解决在有多种算法相似的情况下,使用if…else 或swith…case所带来的复杂性和臃肿性。
在日常业务开发中,策略模式适用于以下场景:

  1. 针对同一类型问题,有多种处理方式,每一种都能独立解决问题;
  2. 算法需要自由切换的场景;
  3. 需要屏蔽算法规则的场景。 策略模式中的上下文环境 (Context) ,其职责本来是隔离客户端与策略类的耦合,让客户端完全与上下文环境沟通,无需关系具体策略。

策略模式的优缺点
优点 :

  1. 策略模式符合开闭原则。
  2. 避免使用多重条件转移语句,如 if…else… 语句、 switch 语句
  3. 使用策略模式可以提高算法的保密性和安全性。

缺点 :

  1. 客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
  2. 代码中会产生非常多策略类,增加维护难度。

三、责任链模式 (Chain of Responsibility Pattern) 是将链中每一个节点看作是一个对象,每个节点处理的清求均不同,且内部自动维护—个下—节点对象。当—个清求从链式的首端发出时,会沿看链的路径依次传递给每—个节点对象,直至有对象处理这个清求为止。
责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解的是其模式(道)而不是其具体实现(术),责任链模式的独到之处是其将节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动了起来。

责任链模式的优缺点 优点:

  1. 将请求与处理解耦;
  2. 请求处理者(节点对象)只需关注自己感兴趣的请求进行处理即可,对于不感兴趣的请求,直接转 发给下一级节点对象;
  3. 具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果;
  4. 链路结构灵活,可以通过改变链路结构动态地新增或删减责任;
  5. 易于扩展新的请求处理类(节点),符合开闭原则。

缺点:

  1. 责任链太长或者处理时间过长,会影响整体性能
  2. 如果节点对象存在循环引用时,会造成死循环,导致系统崩溃;

10. 常用的注解有哪些,有什么作用

一.用于创建对象的注解
作用:和在xml配置文件中编写一个标签实现的功能一样。

  1. @Component : 用于把当前类对象存入Spring容器中。 属性:value — 用于指定bean的id。如果不写该属性,id的默认值是当前类名,且首字母改为小写。
  2. @Controller : 一般用在表现层。
  3. @Service : 一般用在业务层。

二.用于注入数据的注解
作用:和在xml配置文件中的标签中写一个标签的功能一样。

  1. @Autowired : 自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。可以作用在变量或者方法上。
  2. @Qualifier : 在按照类型注入的基础之上再按照名称注入,它在给类成员注入时要和@Autowired配合使用,但是在给方法参数注入是可以单独使用。
  3. @Resource : 直接按照bean的id注入,可以独立使用。 属性:name — 用于指定bean的id。 备注:以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。另外,集合类型的注入只能通过xml来实现。
  4. @Value : 用于注入基本类型和String类型的数据。 属性:value — 用于指定数据的值,它可以使用Spring中的SpEL(也就是Spring中的el表达式)。SpEL的写法:${表达式}

三.用于改变作用范围的注解
作用:和在xml配置文件中的标签中使用scope属性实现的功能一样。

  1. @Scope : 用于指定bean的作用范围。 属性:value — 指定范围的取值。常用取值:singleton(单例)和prototype(多例)。

四.和生命周期相关的注解
作用:和在xml配置文件中的标签中使用init-method和destory-method属性实现的功能一样。

  1. @PreDestory : 用于指定销毁方法。
  2. @PostConstruct : 用于指定初始化方法。

五.Spring新注解

  1. @Configuration : 用于指定当前类是一个配置类。
  2. @ComponentScan : 用于通过注解指定Spring在创建容器时要扫描的包。
  3. @Bean : 用于把当前方法的返回值作为bean对象存入Spring的IOC容器中。 属性:name — 用于指定bean的id。当不写时,默认值为当前方法的名称。
  4. @Import : 用于导入其他的配置类。 属性:value — 用于指定其他配置类的字节码。当我们使用@Import注解时,有@Import注解的类就是父配置类。
  5. @PropertySource : 用于指定properties文件的位置。 属性:value — 指定文件的名称和路径。关键字classpath表示类路径下。
  6. @Entity:@Table(name=”“):表明这是一个实体类。一般用于jpa这两个注解一般一块使用,但是如果表名和实体类名相同的话,@Table可以省略

11. JVM调优的目标是什么

JVM调优的主要目的:减少full gc、降低gc停顿时间、提高吞吐量;调优的顺序=“提高吞吐量”>“降低gc停顿时间”;在满足吞吐量的前提下,再降低gc停顿时间;若不能同时满足以上,则选择最适合系统的一种调优结果
一般JVM调优,重点在于调整JVM堆大小、调整垃圾回收器.
JVM常用命令:

  1. jstat命令用于监视虚拟机的运行状态。命令格式【jstat -参数命令 进程号 间隔毫秒数 总输出次数】
  2. jinfo可以查看启动jar包时未显式指定的系统默认值,以及动态修改这些默认值。命令格式【jinfo -flag 默认的参数 进程id】
  3. jmap查看java内存信息。命令格式【jmap -参数 进程id】
  4. jstack可以查看正在运行的线程的堆栈信息,比如查看后天没有相应的线程在做些什么,在等待什么资源。命令格式【jstack 参数项 进程号】

常见的调优策略

  1. 减少创建对象的数量。
  2. 减少使用全局变量和大对象。
  3. 调整新生代、老年代的大小到最合适。
  4. 选择合适的GC收集器,并设置合理的参数。

微服务体系栈

1. SpringCloud是什么/Cloud Alibaba是什么,有哪些组成与功能

注册中心/RPC/限流熔断、网关/接口治理、配置、事件总线;监控配套:调用链、性能监控;
spring cloud五大组件分别为:

服务发现–Netflix Eureka 主要提供服务的自动注册和发现
客户端负载均衡–Netflix Ribbon
断路器–Netflix Hystrix
服务网关–Netflix Zuul
分布式配置–Spring Cloud Config

此外Ribbon是和Feign以及Eureka紧密协作的,具体如下:
首先Ribbon会从Eureka Client里获取到对应的服务注册表,知道所有的服务都部署在了哪些机器上,在监听哪些端口号。
然后Ribbon就使用默认的Round Robin轮询算法,从中选择一台机器;
最后Feign就会针对这台机器,构造并发起请求。

微服务的框架一般都会分为以下一个大部分:
微服务网关-负责请求转发,路由,权限控制
注册、配置中心–服务发现和注册
客户端负载器—负责微服务内部的负载
限流控制–负责微服务调用的限流和流量控制

2. 了解或者使用过哪些主流厂商微服务框架

蚂蚁SOFA、阿里EDAS、腾讯TSF、京东JSF

3. 对于微服务的降级,限流,熔断怎么理解,项目中怎么使用的,都解决什么问题

熔断和降级的区别?
相同点
都是为了保证服务的可用性,防止系统发生崩溃
都导致了系统的某些服务、功能不可用
不同点
熔断是由某个下游服务故障引起的,降级一般从系统的整体负荷去考虑
在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。
服务熔断解决如下问题:

  1. 当所依赖的对象不稳定时,能够起到快速失败的目的;
  2. 快速失败后,能够根据一定的算法动态试探所依赖对象是否恢复。

自动降级分类
  1)超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况
  2)失败次数降级:主要是一些不稳定的api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况
  3)故障降级:比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)
  4)限流降级:秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)

4. 对于RPC技术原理的理解,RPC整体调用过程

RPC 框架----- 远程过程调用协议RPC(Remote Procedure Call Protocol)-----允许像调用本地服务一样调用远程服务。

总的来说可以归纳为以下几步:
1,远程服务之间建立通讯协议
2,寻址:服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么
3,通过序列化和反序列化进行数据传递
4,将传递过来的数据通过java反射原理定位接口方法和参数

5. 微服务之前的循环依赖问题怎么产生的?有什么解决方案。

循环依赖的坏处
1、服务功能不内聚,耦合严重,导致研发效率低下
假设A依赖B,B又依赖A,会导致每次A和B部署的时候必须耦合,部署了A就得部署B,不然就会报错;
上面这些还不算严重的,比较麻烦的是A升级或者改了些接口,B要测试下;反过来B改了接口A也要测试下,浪费研发和测试资源;
2、增加了系统的复杂性,很容易出错
一些线上操作升级可能也会比较麻烦,像我们在升级JDK8的时候就必须梳理各种依赖关系,梳理不当就可能会有线上故障;
3、系统的扩展性受到限制
这里的扩展性分系统和业务2方面,系统上来说假如大促我要升级扩容,如果正常不依赖其它应用,或者只依赖少量应用,只升级自己就可以了,如果依赖了其它应用,还得考虑其它应用的容量;还涉及到部署的情况,当你的业务做的很大,以前只是垂直应用,现在升级成平台型应用的时候,对部署有了更高的要求,可能要单独的隔离环境进行部署,如果依赖了不依赖的应用,会使这些几乎不可能。
业务扩展性也是一样的,如果业务发展比较快,要支持更多的场景,那就必须考虑新的业务和这些依赖的应用是否兼容,增加研发成本,也不利于扩展。

如何避免循环依赖
按上面的情况,如果应用A依赖B,B依赖A,要做到不循环依赖,有以下办法:
1、改为异步调用
微服务解耦,做到服务自治,可以发送MQ消息,这样发送方就不用关心消费方的存在了。
2、微服务分层建设
对微服务进行分层规划,上层微服务可以调用下层微服务,下层微服务禁止调用上层微服务,把公用的部分沉淀下放到基础微服务层。

分布式体系栈

1. 分布式数据框架,分片规则与扩容,分片访问机制

  1. 数据分片的主要目标是,将一张数据表切分成较小的片,不同片存储到不同服务器上面去,通过分片的方式使用多台服务器存储一张数据表,避免一台服务器记录存储处理整张数据表带来的存储及访问压力。
  1. 数据分片的特点是,数据服务器之间相互独立,不共享任何信息,及时有部分服务器故障了,也不影响整个系统的可用性。另一个特点是通过分片键来定位分片,一个分片存储到哪个服务器上面去,到哪个服务器上面去查找,是通过分片键进行路由分区算法计算出来的。在SQL语句里面,只要包含了分片键,就可以访问特定的服务器,而不需要连接所有的服务器,跟其他的服务器进行通信。
  1. 数据分片的原理是,将数据以某种方式进行切分,通常是用分片键的路由算法进行计算,使每天服务器都只存储一部分数据。
  1. 数据分片的实现,现在有一个专门的分布式数据中间件,来做数据分片的工作Mycat。Mycat是一个专门的分布式数据库中间件,应用程序像连接数据库一样连接Mycat。而数据分片的操作完全交给Mycat去完成。例如,有3个分片数据库服务器-数据库服务器dn1、dn2、dn3,它们的分片规则是根据prov字段进行分片。那么我们执行一个查询操作“seletc * from orders where prov=wuhan”的时候,Mycat会根据分片规则将这条SQL操作路由到dn1这台服务器节点上。dn1执行数据数据查询操作返回结果后,Mycat再返回给应用程序。通过Mycat这样的分布式数据库中间件,无感知的使用分片数据库。同时Mycat还一定程度上支持分片数据库的联合join查询以及数据事务。
  1. 分片数据库的伸缩扩容
    下面来看下分片数据库如何进行扩容伸缩,对于一个新业务刚开始的时候数据量不是很多,两个数据库服务器就够了,但是随着数据的不断增长,可能需要增加第三个、第四个、第五个,甚至更多的服务器。在增加服务器的过程中,分片规则需要改变。通常的做法是数据分片使用逻辑数据库,也就是说一开始虽然两个服务器就可以完成数据分片存储,但是依然在逻辑上把它切分为多个逻辑数据库。例如,我们将数据库切分为32个逻辑数据库,但是开始的时候只有两个物理服务器,我们把32个数据库分别启动在两个物理服务器上。那么路由算法就还是按照32进行路由分区,数据分片也是32片。当需要扩容的时候,只需要把这些逻辑数据库迁移到其他的物理服务器上,就可以完成扩容。因为迁移后数据分片还是32片,数据分片的算法不需要改变。数据迁移也仅仅是将逻辑数据库迁移到新的服务器上面去,而这种迁移通过数据库的主从复制就可以完成。

2. 对于分布式事务理解,有几种方案,具体落地实施。

事务
严格意义上的事务实现应该是具备原子性、一致性、隔离性和持久性,简称 ACID。

分布式事务
分布式事务顾名思义就是要在分布式系统中实现事务,它其实是由多个本地事务组合而成。
对于分布式事务而言几乎满足不了 ACID,其实对于单机事务而言大部分情况下也没有满足 ACID,不然怎么会有四种隔离级别呢?所以更别说分布在不同数据库或者不同应用上的分布式事务了。

2PC
2PC(Two-phase commit protocol),中文叫二阶段提交。 二阶段提交是一种强一致性设计,2PC 引入一个事务协调者的角>色来协调管理各参与者(也可称之为各本地资源)的提交和回滚,二阶段分别指的是准备(投票)和提交两个阶段。

3PC
3PC 的出现是为了解决 2PC 的一些问题,相比于 2PC 它在参与者中也引入了超时机制,并且新增了一个阶段使得参与者可以利用这一个阶段统一各自的状态。
3PC 包含了三个阶段,分别是准备阶段、预提交阶段和提交阶段,对应的英文就是:CanCommit、PreCommit 和 DoCommit。

TCC
2PC 和 3PC 都是数据库层面的,而 TCC 是业务层面的分布式事务,就像我前面说的分布式事务不仅仅包括数据库的操作,还包括发送短信等,这时候 TCC 就派上用场了!

TCC 指的是Try - Confirm - Cancel。
Try 指的是预留,即资源的预留和锁定,注意是预留。
Confirm 指的是确认操作,这一步其实就是真正的执行了。
Cancel 指的是撤销操作,可以理解为把预留阶段的动作撤销了。

TCC 对业务的侵入较大和业务紧耦合,需要根据特定的场景和业务逻辑来设计相应的操作。
还有一点要注意,撤销和确认操作的执行可能需要重试,因此还需要保证操作的幂等。
相对于 2PC、3PC ,TCC 适用的范围更大,但是开发量也更大,毕竟都在业务上实现,而且有时候你会发现这三个方法还真不好写。不过也因为是在业务上实现的,所以TCC可以跨数据库、跨不同的业务系统来实现事务。

本地消息表
本地消息表其实就是利用了 各系统本地的事务来实现分布式事务。
本地消息表顾名思义就是会有一张存放本地消息的表,一般都是放在数据库中,然后在执行业务的时候 将业务的执行和将消息放入消息表中的操作放在同一个事务中,这样就能保证消息放入本地表中业务肯定是执行成功的。

消息事务
RocketMQ 就很好的支持了消息事务,让我们来看一下如何通过消息实现事务。
第一步先给 Broker 发送事务消息即半消息,半消息不是说一半消息,而是这个消息对消费者来说不可见,然后发送成功后发送方再执行本地事务。
再根据本地事务的结果向 Broker 发送 Commit 或者 RollBack 命令。

最大努力通知
本地消息表也可以算最大努力,事务消息也可以算最大努力。
就本地消息表来说会有后台任务定时去查看未完成的消息,然后去调用对应的服务,当一个消息多次调用都失败的时候可以记录下然后引入人工,或者直接舍弃。这其实算是最大努力了
事务消息也是一样,当半消息被commit了之后确实就是普通消息了,如果订阅者一直不消费或者消费不了则会一直重试,到最后进入死信队列。其实这也算最大努力。
所以最大努力通知其实只是表明了一种柔性事务的思想:我已经尽力我最大的努力想达成事务的最终一致了。
适用于对时间不敏感的业务,例如短信通知。

3. 分布式调度,与Quart区别,运行机制。

quartz
支持集群和分布式,可是没有友好的管理界面,功能单一,对于管理调用的任务比较困难。数据库
quartz使用数据库锁。在quartz的集群解决方案里有张表scheduler_locks,quartz采用了悲观锁的方式对triggers表进行行加锁,以保证任务同步的正确性。一旦某一个节点上面的线程获取了该锁,那么这个Job就会在这台机器上被执行,同时这个锁就会被这台机器占用。同时另一台机器也会想要触发这个任务,可是锁已经被占用了,就只能等待,直到这个锁被释放。
quartz的分布式调度策略是以数据库为边界资源的一种异步策略。各个调度器都遵照一个基于数据库锁的操做规则从而保证了操做的惟一性。同时多个节点的异步运行保证了服务的可靠。但这种策略有本身的局限性:集群特性对于高CPU使用率的任务效果很好,可是对于大量的短任务,各个节点都会抢占数据库锁,这样就出现大量的线程等待资源。这种状况随着节点的增长会愈来愈严重。服务器
缺点:quartz的分布式只是解决了高可用的问题,并无解决任务分片的问题,仍是会有单机处理的极限。

xxl-job
轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。负载均衡
主要特性框架:

简单:支持经过Web页面对任务进行CRUD操做,操做简单,一分钟上手;
调度中心HA(中心式):调度采用中心式设计,“调度中心”基于集群Quartz实现并支持集群部署,可保证调度中心HA;
执行器HA(分布式):任务分布式执行,任务"执行器"支持集群部署,可保证任务执行HA;
弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会从新分配任务;
分片广播任务:执行器集群部署时,任务路由策略选择"分片广播"状况下,一次任务调度将会广播触发>集群中全部执行器执行一次任务,可根据分片参数开发分片任务;
动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增长分片数量,>协同进行业务处理;在进行大数据量业务操做时可显著提高任务处理能力和速度。
动态:支持动态修改任务状态、暂停/恢复任务,以及终止运行中任务,即时生效;
注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
一致性:“调度中心”经过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
其余特性运维
路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性>HASH、最不常用、最近最久未使用、故障转移、忙碌转移等;
故障转移:任务路由策略选择"故障转移"状况下,若是执行器集群中某一台机器故障,将会自动Failover切换到一台正常的执行器发送调度请求。
阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖以前调度;
任务超时控制:支持自定义任务超时时间,任务运行超时将会主动中断任务;
任务失败重试:支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;其中分片任务支持分片粒度的失败重试;
任务失败告警;默认提供邮件方式失败告警,同时预留扩展接口,可方面的扩展短信、钉钉等告警方式;
事件触发:除了"Cron方式"和"任务依赖方式"触发任务执行以外,支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务,可根据业务事件灵活触发。
任务进度监控:支持实时监控任务进度;
脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS、PHP、PowerShell等类型脚本;
调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
数据加密:调度中心和执行器之间的通信进行数据加密,提高调度信息安全性;
邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行;
功能齐全,文档也很齐全,有使用教程,可是上手门槛稍微高了;

Elastic-Job
分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成。
Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务。
Elastic-Job-Cloud使用Mesos + Docker的解决方案,额外提供资源治理、应用分发以及进程隔离等服务。
轻量级无中心化:Elastic-Job-Lite并没有做业调度中心节点,而是基于部署做业框架的程序在到达相应时间点时各自触发调度。
灵活的增删改查做业,集中式管理调度做业
支持高可用:一旦执行做业的服务器崩溃,等待执行的服务器将会在下次做业启动时替补执行。开启失效转移功能效果更好,能够保证在本次做业执行时崩溃,备机当即启动替补执行。
支持分片:做业分片一致性,保证同一分片在分布式环境中仅一个执行实例
任务监控:经过监听Elastic-Job-Lite的zookeeper注册中心的几个关键节点便可完成做业运行状态监控功能
一致性:使用zookeeper做为注册中心,为了保证做业的在分布式场景下的一致性,一旦做业与注册中心没法通讯,运行中的做业会马上中止执行,但做业的进程不会退出,这样作的目的是为了防止做业重分片时,将与注册中心失去联系的节点执行的分片分配给另外节点,致使同一分片在两个节点中同时执行。
同时支持动态扩容,将任务拆分为n个任务项后,各个服务器分别执行各自分配到的任务项。一旦有新的服务器加入集群,或现有服务器下线,elastic-job将在保留本次任务执行不变的状况下,下次任务开始前触发任务重分片

4. 分布式CAP定理-BASE理论理解

CAP是分布式系统的指导理论,是NoSQL数据库的理论基石。CAP其实就是对分布式系统的特性总结,即一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。
分区容错性,就是CAP中的P,这一项其实是必选项,CAP主要用在分布式系统中,所谓分布式就表示有多个服务器或节点,比如数据库的主从配置。如果不要P,那只是个单机服务,就不需要CAP来指导了。
数据一致性,就是CAP中C,这一项表示分布式系统中的每个服务或节点对外提供的数据必须得一致,比如数据在A数据库被修改了,必须立刻同步至其他(比如B)数据库服务器上。客户端访问B数据库时必须是最新的数据,否则不提供服务。
可用性,就是CAP中A,搞分布式系统最主要的目的是实现高可用,即一台服务器崩了,还有其他节点继续提供服务。同时还能实现数据的安全,比如数据库同步备份等。
其实同时实现数据一致性和可用性是互相矛盾的,想实现可用性,就要放弃数据一致性。分区容错性是必选的,所以留给我们的选项只有CP或AP。

CP,即实现一致性和分区容错性,此组合为数据强一致性模式,即要求多服务之间数据一定要一致,牺牲了可用性,比如操作A服务时,就要让其他服务不可用,一些对数据要求比较高的场景使用此方式,比如涉及金钱等。这种模式性能很低。实现强一致性的方案有2PC(两阶段提交)。

AP,即实现可用性和分区容错性,此组合为数据最终一致性模式,即要求所有服务都可用,牺牲了数据一致性,比如操作A服务修改数据,同时读取B服务查询时发现数据还是旧数据,但过一会数据就会一致,互联网分布式服务多数基于AP,Base模式也是基于AP组合。实现最终一致性的方案有TCC、消息队列、Saga等,其中消息队列用的最多。

BASE,即Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)。它是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论。互联网中对可用性要求非常高,但对一致性要求要少点,比如发一个消息给用户,用户不用立即收到,晚个一两秒也OK的。所以可以牺牲CAP中C,BASE理论大部分是对AP的补充和权衡。

Basically Available(基本可用),它是要求分布式系统中所有节点要做到高可用。

Soft State(软状态),它定义数据可以有一个中间状态,比如服务A更新数据,读取B服务时,允许存在一定的延迟,客户端读取的为中间状态。

Eventually Consistent(最终一致性),它允许数据存在中间状态,做不到强一致性,但要做到最终一致性,比如消息列表多刷几次,总归能刷出来。

5. 分布式序列:生成策略,全局唯一如何保证。

序列常用算法
UUID组成:
标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12)。
优点:

  1. 本地生成,无依赖,速度极快,序号个数无限。
  2. 序号全局唯一性。
    不足:
  3. 序列无规律,对索引不友好。
  4. 字段串由数字与字母成合,存储空间大。

雪化算法(snowflake)
优点:

  1. 本地生成,无依赖。
  2. 整型,趋势递增,有利于索引。
  3. 效率较高,理论每节点每秒最大能产生26万ID。

不足:

  1. 依赖机器时间,如果发生时钟回拨会导致可能生成id重复。
  2. workid节点有限,无存储容易碰撞,在超大服务集群使用有风险。

基于DB数据段算法
利用DB表的存储机制,表主要字段有:命名空间、当前最大值、步长、版本号。通过步长的大小及利用缓存数据段来控制,解决DB的性能瓶颈,提高效率。
优点:

  1. 高性能,序列无极限(取决于步长长度)。
  2. 整型,有顺序,趋势递增,有利于索引。
  3. 可以自定义value的大小,非常方便业务从原有的ID方式迁移过来。

不足:

  1. 服务强依赖DB,来存储业务场景、最大值、步长等信息。
  2. 中心化部署,序列号段缓存服务节点,对序列服务可靠性要求极高。

序列部署方式(中心化 & 分布式)
中心化部署:
中心化部署是指:序列以微服务的方式单部署,连接独立的序列库。提供Http、RPC、restful等协议的接口,给各应用调用并返回序列或号段。
分布式部署:
分布式部署是指:序列以组件JAR的方式,应用有机的结合一起部署,把序列的相关表,与应用的数据表放一个库,共用数据源。
目前的解决方案:都是在snowflake、基于DB数据段两大基础算法及结合自身的特点做优化。

中间件体系栈

1. 用过哪些中间件,什么作用,完成什么业务?

网关Nginx、Kong、Zuul
缓存Redis、MemCached、OsCache、EhCache
搜索ElasticSearch、Solr
熔断Hystrix、resilience4j
负载均衡DNS、F5、LVS、Nginx、OpenResty、HAproxy
注册中心Eureka、Zookeeper、Redis、Etcd、Consul
认证鉴权JWT、SpringSecurity
消费队列RabbitMQ、Kafka、RocketMQ、ActiveMQ、Redis
系统监控Grafana、Prometheus、Influxdb、Telegraf、Lepus
文件系统OSS、NFS、FastDFS、MogileFS
RPC框架Dubbo、Motan、Thrift、grpc
构建工具Maven、Gradle
集成部署Docker、Jenkins、Git、Maven
分布式配置Disconf、Apollo、Spring Cloud Config、Diamond
压测LoadRunner、JMeter、AB、webbench
数据库MySQL、Redis、MongoDB、PostgreSQL、Memcache、HBase
网络专用网络VPC、弹性公网IP、CDN
数据库中间件DRDS、Mycat、360 Atlas、Cobar
分布式框架Dubbo、Motan、Spring-Could
分布式任务XXL-JOB、Elastic-Job、Saturn、Quartz
分布式追踪Pinpoint、CAT、zipkin
分布式日志elasticsearch、logstash、Kibana 、redis、kafka
版本发布蓝绿部署、A/B测试、灰度发布/金丝雀发布

2. redis:数据一致性,雪崩击穿穿透。

Redis概述:
redis是一个内存数据库, 因此数据基本上都存在于内存当中
但是Redis会定时以追加或者快照的方式刷新到硬盘中.
由于redis是一个内存数据库, 所以读取写入的速度是非常快的, 所以经常被用来做数据, 页面等的缓存。

redis保证缓存一致性:

  1. 先更新数据库,再删除缓存
    这种方式可能存在以下两种异常情况
    更新数据库失败,这时可以通过程序捕获异常,直接返回结果,不再继续删除缓存,所以不会出现数据不一致的问题
    更新数据库成功,删除缓存失败。导致数据库是最新数据,缓存中的是旧数据,数据不一致
    第2种情况应该怎么办呢?我们有两种方式:失败重试和异步更新。
    (1)失败重试
    如果删除缓存失败,我们可以捕获这个异常,把需要删除的 key 发送到消息队列。自己创建一个消费者消费,尝试再次删除这个 key,直到删除成功为止。
    这种方式有个缺点,首先会对业务代码造成入侵,其次引入了消息队列,增加了系统的不确定性。
    (2)异步更新缓存
    因为更新数据库时会往 binlog 中写入日志,所以我们可以启动一个监听 binlog变化的服务(比如使用阿里的 canal开源组件),然后在客户端完成删除 key 的操作。如果删除失败的话,再发送到消息队列。
    总之,对于删除缓存失败的情况,我们的做法是不断地重试删除操作,直到成功。无论是重试还是异步删除,都是最终一致性的思想。
  2. 先删除缓存,再更新数据库
    这种方式可能存在以下两种异常情况
    删除缓存失败,这时可以通过程序捕获异常,直接返回结果,不再继续更新数据库,所以不会出现数据不一致的问题
    删除缓存成功,更新数据库失败。在多线程下可能会出现数据不一致的问题
    这时,Redis中存储的旧数据,数据库的值是新数据,导致数据不一致。这时我们可以采用延时双删的策略,即更新数据库数据之后,再删除一次缓存。

一、缓存穿透(查不到)
用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于 是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是 都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
解决方案

  1. 布隆过滤器
    布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则 丢弃,从而避免了对底层存储系统的查询压力;
  2. 缓存空对象
    当缓存层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
    但是这种方法会存在两个问题:
    1. 如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;
    2. 即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

二、缓存击穿(量太大,缓存过期)
大量用户请求去请求同一个东西,这个时候缓存某个key设置的过期时间是60s,60.1s缓存恢复了,在这0.1s的时间内,大量的请求就跑到了MySQL关系型数据库里面了,容易使数据库宕机,这就是击穿!
这里需要注意和缓存穿透的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一 个屏障上凿开了一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访 问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。

解决方案

  1. 设置热点数据永不过期
    从缓存层面来看,没有设置过期时间,所以不会出现热点 key 过期后产生的问题。
  2. 加互斥锁
    分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大!

三、缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。(比如说停电了,Redis宕机!)
产生雪崩的原因之一,比如马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然 形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。
解决方案

  1. redis高可用
    这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续 工作,其实就是搭建的集群。(异地多活!)
  2. 限流降级
    这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
  3. 数据预热
    数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

3. redis:集群高可用原理,集群节点故障转移过程。

实现redis高可用机制的一些方法
保证redis高可用机制需要redis主从复制、redis持久化机制、哨兵机制、keepalived等的支持。

redis主从复制原理
首先主从复制需要分为两个角色:master(主) 和 slave(从) ,注意:redis里面只支持一个主,不像Mysql、Nginx主从复制可以多主多从。
(1)redis的复制功能是支持多个数据库之间的数据同步。一类是主数据库(master)一类是从数据库(slave),主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。
(2)通过redis的复制功能可以很好的实现数据库的读写分离,提高服务器的负载能力。主数据库主要进行写操作,而从数据库负责读操作。
Redis主从复制可以根据是否是全量分为全量同步和增量同步,Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。

故障转移
redis集群实现了高可用,当集群内少许节点出现故障时,经过故障转移能够保证集群正常对外提供服务。当集群里某个节点出现了问题,redis集群内的节点经过ping pong消息发现节点是否健康,是否有故障,其实主要环节也包括了:主观下线和客观下线;主观下线:指某个节点认为另外一个节点不可用,即下线状态,固然这个状态不是最终的故障断定,只能表明这个节点自身的意见,也有可能存在误判;

下线流程: A,节点a发送ping消息给节点b ,若是通讯正常将接收到pong消息,节点a更新最近一次与节点b的通讯时间; B,若是节点a与节点b通讯出现问题则断开链接,下次会进行重连,若是一直通讯失败,则它们的最后通讯时间将没法更新; 节点a内的定时任务检测到与节点b最后通讯时间超过cluster_note-timeout时,更新本地对节点b的状态为主观下线(pfail) 客观下线:指真正的下线,集群内多个节点都认为该节点不可用,达成共识,将它下线,若是下线的节点为主节点,还要对它进行故障转移 假如节点a标记节点b为主观下线,一段时间后节点a经过消息把节点b的状态发到其它节点,当节点c接受到消息并解析出消息体时,会发现节点b的pfail状态时,会触发客观下线流程; 当下线为主节点时,此时redis集群为统计持有槽的主节点投票数是否达到一半,当下线报告统计数大于一半时,被标记为客观下线状态。

4. MQ:消息确认送达机制,高可用架构的原理

MQ要想尽量消息必达,架构上有两个核心设计点:
(1)消息落地
(2)消息超时、重传、确认
MQ消息投递
上半场MQ-client-sender到MQ-server流程:
(1)MQ-client将消息发送给MQ-server(此时业务方调用的是API:SendMsg)
(2)MQ-server将消息落地,落地后即为发送成功
(3)MQ-server将应答发送给MQ-client(此时回调业务方是API:SendCallback)
MQ消息投递下半场,MQ-server到MQ-client-receiver流程:
(1)MQ-server将消息发送给MQ-client(此时回调业务方是API:RecvCallback)
(2)MQ-client回复应答给MQ-server(此时业务方主动调用API:SendAck)
(3)MQ-server收到ack,将之前已经落地的消息删除,完成消息的可靠投递

MQ高可用架构的原理
RocketMQ要保证高可用的话,可以使用主从架构,也就是将Broker分为Master Broker和Slave Broker。
与其他传统的主从架构一样,Master负责接收数据之后,再将数据同步给Slave,Master和Slave都会向NameServer注册路由信息,同时每隔30秒发送一次心跳。RocketMQ主从架构数据同步采用的是Pull模式,Slave不停的发送请求到Master上去拉取消息
与其他传统的主从架构不一样的是,RocketMQ的主从架构并不是纯粹的读写分离。写的话还是依靠Master,而读的话,既可能是从Master读,也可能是从Slave读,这取决于Master
读消息的时候,第一次是从Master上去读的,之后是去Master还是Slave上读消息,是由Master根据自身的负载情况和Slave的数据同步情况来向消费者建议。如果Master的写负载已经很高的话,那么就会建议消费者下次拉取消息的话就去Slave上拉取;如果Slave数据同步较慢,还没有完全同步Master的消息的话,那么下一次还是会来Master上拉取消息
当Master节点宕机之后,一般来说会对Slave节点进行选举然后选出新的Master继续提供服务。

5. MQ:怎么保证消息的一致性,不重复消费。

MQ消息一致性
1、事务消息与普通消息的区别就在于消息生产环节,生产者首先预发送一条消息到MQ(这也被称为发送half消息)
2、MQ接受到消息后,先进行持久化,则存储中会新增一条状态为待发送的消息
3、然后返回ACK给消息生产者,此时MQ不会触发消息推送事件
4、生产者预发送消息成功后,执行本地事务
5、执行本地事务,执行完成后,发送执行结果给MQ
6、MQ会根据结果删除或者更新消息状态为可发送
7、如果消息状态更新为可发送,则MQ会push消息给消费者,后面消息的消费和普通消息是一样的
注意点:由于MQ通常都会保证消息能够投递成功,因此,如果业务没有及时返回ACK结果,那么就有可能造成MQ的重复消息投递问题。因此,对于消息最终一致性的方案,消息的消费者必须要对消息的消费支持幂等,不能造成同一条消息的重复消费的情况。
事务消息,producer不会因为consumer消费失败而做回滚,采用事务消息的应用,其所追求的是高可用和最终一致性,消息消费失败的话,MQ自己会负责重推消息,直到消费成功。因此,事务消息是针对生产端而言的,而消费端,消费端的一致性是通过MQ的重试机制来完成的。

解决消息重复消费,其实就是保证消息的消费幂等性。利用数据库的唯一约束
在进行消息消费,需要取一个唯一个标识,比如 id 作为唯一约束字段,先添加数据,如果添加失败,后续做错误提示,或者不做后续操作。

1.Redis 设置全局唯一id
每次生产者发送消息前设置一个全局唯一id放在消息体重,并存放的 redis 里,在消费端接口上先找在redis 查看是否存在全局id,如果存在,调用消费接口并删除全局id,如果不存在,不做后续操作。
2.多版本(乐观锁)机制
给业务数据添加一个版本号,每次更新数据前,比如当前版本和消息中的版本是否一致,如果一致就更新数据并且版本号+1,如果不一致就不跟新。这有点类似乐观锁处理机制。

数据库能力栈

1. 数据库设计的第一范式,第二范式和第三范式

第一范式
无重复的列
数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性
在任何一个关系数据库中,第一范式(1NF)是对关系模式的设计基本要求,一般设计中都必须满足第一范式(1NF)。不过有些关系模型中突破了1NF的限制,这种称为非1NF的关系模型。换句话说,是否必须满足1NF的最低要求,主要依赖于所使用的关系模型。
第二范式
属性完全依赖于主键
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
当存在多个主键的时候,才会发生不符合第二范式的情况。比如有两个主键,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式。
如果存在不符合第二范式的情况,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。
第三范式
属性不能传递依赖于主属性(属性不依赖于其它非主键属性)
第三范式(3NF)是在第二范式(2NF)的基础上建立起来的,即满足第三范式(3NF)必须先满足第二范式(2NF)。
如果某一属性依赖于其他非主键属性,而其他非主键属性又依赖于主键,那么这个属性就是间接依赖于主键,这被称作传递依赖于主属性。

2. 数据库执行计划怎么查看,需要关注哪些?

什么是数据库执行计划:
利用一个SQL语句, 你可能要Server取出所有News表中的信息. 当Server收到的这条SQL的时候, 第一件事情并不是解析它. 如果这条SQL没有语法错误, Server才会继续工作. Server会决定最好的计算方式. Server会选择, 是读整个News表好呢, 还是利用索引会比较快些. Server会比较所有可能方法所耗费的资源. 最终SQL语句被物理性执行的方法被称做执行计划或者是查询计划.
数据库执行计划怎么查看?(使用PL/SQL、navicat等客户端工具查看)

  1. 通过SQL*PLUS中的autotrace命令查看
    (1)set autotrace on --(得到执行计划,并输出结果)
    (2)set autotrace traceonly --(得到执行计划,但不输出结果)
    (3)set autotrace traceonly explain --(得到执行计划,不输出统计信息和结果,仅展现执行计划部分)
    (4)set autotrace traceonly statistics --(不输出执行计划和结果,仅展现统计信息)
  2. explain plan for获取
    执行步骤如下:
    SQL> set linesize 200;
    SQL> set pagesize 2000;
    SQL> explain plan for
    select * from emp; --要解析的SQL脚本
    Explained
    SQL> select * from table(dbms_xplan.display());

查询执行计划需要关注哪些参数
1)基数(Rows):Oracle估计的当前操作的返回结果集行数
2)字节(Bytes):执行该步骤后返回的字节数
3)耗费(Cost)、CPU耗费:Oracle估计的该步骤的执行成本,用于说明SQL执行的代价,理论上越小越好(该值可能与实际有出入)
4)时间(Time):Oracle估计的当前操作所需的时间
5)访问谓词:where后面的查询条件

3. 做过什么SQL优化

sql优化的方法
1.SQL语句中IN包含的值不应过多,in 和 not in 也要慎用,否则会导致全表扫描
2.SELECT语句务必指明字段名称(SELECT增加很多不必要的消耗(CPU、IO、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时,前断也需要更新)
3.当只需要一条数据的时候,使用limit 1
4.如果排序字段没有用到索引,就尽量少排序
5.如果限制条件中其他字段没有索引,尽量少用or
6.尽量用union all代替union(union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。当然,union all的前提条件是两个结果集没有重复数据)
7.使用合理的分页方式以提高分页的效率
8.避免在where子句中对字段进行null值判断(对于null的判断会导致引擎放弃使用索引而进行全表扫描)
9.不建议使用%前缀模糊查询(LIKE“%name”或者LIKE“%name%”,这种查询会导致索引失效而进行全表扫描。但是可以使用LIKE “name%”)
10.避免在where子句中对字段进行表达式操作(比如:select user_id,user_project from user_base where age
2=36;)
11.避免隐式类型转换
12.对于联合索引来说,要遵守最左前缀法则
13.避免频繁创建和删除临时表,以减少系统表资源的消耗

4. Oracle 分区是什么

什么是分区
分区的实质是把一张大表的数据按照某种规则使用多张子表来存储。然后这多张子表使用统一的表名对外提供服务,子表实际对用户不可见。类似于在多张子表上建立一个视图,然后用户直接使用该视图来访问数据。

为什么要使用分区
当一张表的数据量到达上亿行的时候,表的性能会严重降低,这个时候就需要用到分区了,通过划分成多个小表,并在每个小表上建立本地索引可以大大缩小索引数据文件的大小,从而更快的定位到目标数据来提升访问性能。
分区除了可以用来提升访问性能外,还因为可以指定分区所使用的表空间,因此也用来做数据的生命周期管理。当前需要频繁使用的活跃数据可以放到访问速度更快但价格也更贵的存储设备上,而2、3年前的历史数据,或者叫冷数据可以放到更廉价、速度更低的设备上。从而降低存储费用。
简单分区
常用的分区方法有RANGE、HASH、LIST 3 种。
range分区通常用来对时间或数字进行分区,list分区用来把不相关的数据组织到一起,hash让数据均匀的分布到各个分区中。另外为了方便对范围分区进行管理,oracle还提供了range分区的增强类型interval(间隔)分区,当有新写入的数据的分区值超过了当前分区范围的最大值的时候,它会以分区范围的当前最大值为基数,以指定的interval 为区间,自动创建一个新分区.

集成架构能力

1. JAVA网络编程,了解使用过哪些网络协议

网络通信协议
物理层(Physical Layer):局部局域网上传送数据框(frame),它负责管理电脑通信设备和网络媒体之间的互通,通过物理电气接口实现互联设备间的比特形式的信息传输
数据链路层(Data Link Layer):负责网络寻址、错误侦测和改错,是网络相邻节点设备间二进制信息传输的数据通道,负责数据通道的建立和拆除。
网络层(Network Layer):决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组,解决跨越多个链路的甚至不同网络设备之间的通信问题,是一种端到端的通信
传输层(Transport Layer):把传输表头(TH)加至数据以形成数据包,解决处于不同网络设备间的通信传输、通信管理,对上层需要通信的数据信息分解为标准的数据单元,这些数据单元到达终端后能对这些数据单元进行重新排序和整合。
会话层(Session Layer):负责在数据传输中设置和维护电脑网络中两台电脑之间的通信连接,为用户交互信息而按特点规律建立的连接,提供会话地址和会话管理服务
表示层(Presentation Layer):将会话层得到的数据转化为应用层可以理解的表达形式,或则将数应用层数据转化为会话层可以传输的形式
应用层(Application Layer):提供为应用软件而设的界面,以设置与另一应用软件之间的通信

TCP与UDP
TCP与UDP都是传输层的协议

TCP (Transmission Control Protocol)——传输控制协议
UDP (User Data Protocol)——用户数据报协议
TCP协议的连接过程为:设主机A与主机B建立连接,主机A先发送一个特殊的“连接请求消息段”给B,B接收到消息后就分配相应的资源(接收缓存和发送缓存)给这个TCP连接,然后给A发送一个“允许连接消息段”,A收到这个消息段后也分配相应资源,然后给B发送“确认消息段”,这是就建立起了TCP连接,可以相互传输数据。A与B之间的连接要连续交换3次消息(三次握手法),保证了连接传输的可靠性。
UDP完全依赖IP协议,是无连接的协议,每个数据报都是独立的信息,可能以任何可能的路径传向目的地,传输的可靠性不能被保证。

2. TCP协议的三次握手和四次挥手过程

  1. 三次握手
    概念:指在发送数据的准备阶段,服务器和客户端之间需要三次交互。
    第一次握手:建立连接时,客户端向服务器发送一个SYN包,并进入SYN_SENT状态,等待服务器确认
    第二次握手:当服务器收到客户端的请求后,此时要给客户端给一个确认信息ACK,同时发送SYN包,此时服务器进入 SYN_RECV状态
    第三次握手:客户端收到服务器发的ACK+SYN包后,向服务器发送ACK,发送完毕之后,客户端和服务器进入 ESTABLISHED(TCP连接成功)状态,完成三次握手
  2. 四次挥手
    概念:所谓四次挥手就是说关闭TCP连接的过程,当断开一个TCP连接时,需要客户端和服务器共发送四个包确认。
    第一次挥手:客户端发送一个FIN,用来关闭客户端到服务器的数据传输,客户端进入FIN_WAIT_1状态
    第二次挥手:服务器收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序 号),服务器进入CLOSE_WAIT状态
    第三次挥手:服务器发送一个FIN,用来关闭服务器到客户端的数据传输,服务器进入LAST_ACK状态
    第四次挥手:客户端收到FIN后,客户端进入TIME_WAIT状态,接着发送一个AKC给服务器,确认序号为收到序号+1,服务器进入CLOSED状态,完成四次挥手

常见的问题

  1. 为什么连接需要三次,关闭的时候需要四次?
    当服务器收到客户端的连接请求后,可以直接发送SYN+ACK报文,其中ACK是确认应答,SYN报文是用来同步的。但是在关闭连接的时候,当服务器收到FIN的时候,很可能并不会立刻关闭SOCKET,所以只能先回个ACK来应答,只有等服务器把所有报文都发完了才能发送FIN,因此不能一起发送,所以需要四步。
  2. 为什么断开链接的时候客户端设置的定时器时间等待要2MSL(两个通信报文的最大时间)?
    当客户端最终告诉服务器断开确认的时候,他不知道自己的发出的指令是否准确的一次性被服务器接收。
  3. 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
    虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
  4. 为什么要三次握手?
    三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收机能正常。
    第一次握手:Client什么都不能确认;Server确认了对方发送正常
    第二次握手:Client确认了:自己发送、接收正常,对方发送、接收正常;Server确认了:自己接收正常,对方发送正常
    第三次握手:Client确认了:自己发送、接收正常,对方发送、接收正常;Server确认了:自己发送、接收正常,对方发送接收正常
    所以三次握手就能确认双发收发功能都正常,缺一不可。
  5. 为什么要发送特定的数据包,随便发不行吗?
    三次握手的另外一个目的就是确认双方都支持TCP,告知对方用TCP传输。
    第一次握手:Server 猜测Client可能要建立TCP请求,但不确定,因为也可能是Client乱发了一个数据包给自己
    第二次握手:通过ack=J+1,Client知道Server是支持TCP的,且理解了自己要建立TCP连接的意图
    第三次握手:通过ack=K+1,Server知道Client是支持TCP的,且确实是要建立TCP连接

3. 开发过程中怎么提高开发质量

  1. 无设计不编程,设计先行。
  2. 做好代码评审,交叉互申。
  3. 面向异常编程,做好白盒单元测试。

4. 客户端发起连接出现大量的timewait的原因,怎么处理

TIME_WAIT原因
HTTP 请求中,如果 connection 头部取值被设置为 close 时,基本都由服务端发起主动关闭连接
TCP 四次挥手关闭连接机制中,为了保证 ACK 重发和丢弃延迟数据,设置 time_wait 为 2 倍的 MSL(报文最大存活时间)
解决方法
服务器端允许 time_wait 状态的 socket 被重用
缩减 time_wait 时间,设置为 1 MSL
修改内核参数:
编辑内核文件/etc/sysctl.conf,加入以下内容:
net.ipv4.tcp_syncookies = 1 %表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 %表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 %表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_timestamps = 1 %缩减 time_wait 时间,设置为 1 MSL

需客户端在创建TCP连接时设置soliger参数
当我们调用Socket的close方法时,默认的行为是当底层网卡所有数据都发送完毕后,关闭连接
通过setSoLinger方法,我们可以修改close方法的行为

  1. setSoLinger(true, 0)
    当网卡收到关闭连接请求后,无论数据是否发送完毕,立即发送RST包关闭连接
  2. setSoLinger(true, delay_time)
    当网卡收到关闭连接请求后,等待delay_time
    如果在delay_time过程中数据发送完毕,正常四次挥手关闭连接
    如果在delay_time过程中数据没有发送完毕,发送RST包关闭连接

5. 对于系统并发量,TPS的理解

并发量:系统同时处理的request/事务数
TPS(每秒处理的事务数目) 即Transactions Per Second的缩写。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数,最终利用这些信息作出的评估分。
QPS (每秒能处理查询数目)即Queries Per Second的缩写。是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
计算关系:
QPS = 并发量 / 平均响应时间
并发量 = QPS * 平均响应时间

6. Linux常用命令

Linux常用命令

ls命令:就是 list 的缩写,通过 ls 命令不仅可以查看 linux 文件夹包含的文件,而且可以查看文件权限(包括目录、文件夹、文件权限)查看目录信息等等。

cd 命令:切换当前目录至 dirName。

pwd 命令:pwd 命令用于查看当前工作目录路径。

mkdir 命令:mkdir 命令用于创建文件夹。

rm 命令:删除一个目录中的一个或多个文件或目录,如果没有使用 -r 选项,则 rm 不会删除目录。如果使用 rm 来删除文件,通常仍可以将该文件恢复原状。

rmdir 命令:从一个目录中删除一个或多个子目录项,删除某目录时也必须具有对其父目录的写权限。

mv 命令:移动文件或修改文件名,根据第二参数类型(如目录,则移动文件;如为文件则重命令该文件)。

cp 命令:将源文件复制至目标文件,或将多个源文件复制至目标目录。(命令行复制,如果目标文件已经存在会提示是否覆盖,而在 shell 脚本中,如果不加 -i 参数,则不会提示,而是直接覆盖!)

cat 命令:cat 主要有三大功能:(1.一次显示整个文件,2.从键盘创建一个文件,3.将几个文件合并为一个文件)

more 命令:功能类似于 cat, more 会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会往回(back)一页显示。

less 命令:less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会加载整个文件。

head 命令:head 用来显示档案的开头至标准输出中,默认 head 命令打印其相应文件的开头 10 行。

tail 命令:用于显示指定文件末尾内容,不指定文件时,作为输入信息进行处理。常用查看日志文件。

which 命令:在 linux 要查找某个文件,但不知道放在哪里了,可以使用命令+参数来查找。

whereis 命令:whereis 命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。如果省略参数,则返回所有信息。whereis及 locate 都是基于系统内建的数据库进行搜索,因此效率很高,而find则是遍历硬盘查找文件。

locate 命令:locate 通过搜寻系统内建文档数据库达到快速找到档案,数据库由 updatedb 程序来更新,updatedb 是由 cron daemon 周期性调用的。默认情况下 locate 命令在搜寻数据库时比由整个由硬盘资料来搜寻资料来得快,但较差劲的是 locate 所找到的档案若是最近才建立或刚更名的,可能会找不到,在内定值中,updatedb 每天会跑一次,可以由修改 crontab 来更新设定值 (etc/crontab)。

find 命令:用于在文件树中查找文件,并作出相应的处理。

chmod 命令:用于改变 linux 系统文件或目录的访问权限。用它控制文件或目录的访问权限。该命令有两种用法。一种是包含字母和操作符表达式的文字设定法;另一种是包含数字的数字设定法。

chown 命令:chown 将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户 ID;组可以是组名或者组 ID;文件是以空格分开的要改变权限的文件列表,支持通配符。

df 命令:显示磁盘空间使用情况。获取硬盘被占用了多少空间,目前还剩下多少空间等信息,如果没有文件名被指定,则所有当前被挂载的文件系统的可用空间将被显示。

du 命令:du 命令也是查看使用空间的,但是与 df 命令不同的是 Linux du 命令是对文件和目录磁盘使用的空间的查看

ln 命令:功能是为文件在另外一个位置建立一个同步的链接,当在不同目录需要该问题时,就不需要为每一个目录创建同样的文件,通过 ln 创建的链接(link)减少磁盘占用量。

date 命令:显示或设定系统的日期与时间。

grep 命令:强大的文本搜索命令,grep(Global Regular Expression Print) 全局正则表达式搜索。

wc 命令:wc(word count)功能为统计指定的文件中字节数、字数、行数,并将统计结果输出

ps 命令:ps(process status),用来查看当前运行的进程状态,一次性查看,如果需要动态连续结果使用 top

top 命令:显示当前系统正在执行的进程的相关信息,包括进程 ID、内存占用率、CPU 占用率等

kill 命令:发送指定的信号到相应进程。不指定型号将发送SIGTERM(15)终止指定进程。如果任无法终止该程序可用"-KILL" 参数,其发送的信号为SIGKILL(9) ,将强制结束进程,使用ps命令或者jobs 命令可以查看进程号。root用户将影响用户的进程,非root用户只能影响自己的进程。

free 命令:显示系统内存使用情况,包括物理内存、交互区内存(swap)和内核缓冲区内存。

7. 网络排查常用命令

网络排查常用命令

  1. ping IP [查看网络的连通性]
  2. traceroute IP [显示数据包达到目的地址所经过的路径]
  3. route [查看路由表,以配置路由路径]
  4. arp [查看网络中其他主机的IP地址,常用的就是arp -a]
  5. netstat [显示活动的TCP连接、计算机侦听的端口、以太网统计信息、IP 路由表]
  6. nc [网络连通性测试和端口扫描]

8. 版本管理策略机制,投产与回退—怎么能做对

版本管理策略机制,投产与回退—怎么能做对
投产后问题,往往是开发过程有问题。
例:投产时sql脚本无法成功执行
问题:测试环境中没有按照正常流程提测版本,或者没有验证投产版本
例:投产时出现异常信息
问题:需求开发完成之后单元测试没有做到位
例:测试环境正常运行部署到生产无法正常运行
问题:开发时未以生产环境为准,不明确地方没有及时去生产确认
正确流程:

  1. 拿到需求时认真仔细分析需求,并出详细设计文档
  2. 详细设计需进行评审,评审通过后可开始开发工作
  3. git分支需按照规范进行创建
  4. 开发时有问题需及时沟通,风险及时报备
  5. 每天下班后及时提交代码,便于组长或其他同时互审代码,早发现问题早解决
  6. 需求开发完成之后需编写单元测试案例文档,注:单元测试案例文档先行,完成后方可开始单元测试
  7. 单元测试完成之后需检查所有开发内容是否提交,包括代码和脚本
  8. 送测需求版本时需按照约定规范进行,严禁个人擅自打版本跑脚本
  9. 确定需求投产窗口后需完成投产时序编写,时序文档需体现出当晚所要执行的步骤、技术验证、业务验证以及回退步骤
  10. 投产版本产出后需进行模拟生产验证,如sql脚本需在linux服务器执行
    投产完成之后需做好后续验证,以及运行状况观察。

9. 系统高可用部署方案有哪些

系统高可用部署,双中心部署
应用系统双中心部署,在这种工作模式下,用户所有的业务系统同时在两个数据中心运行,同时为用户提供服务,当某个数据中心的应用系统出现问题时,有另一个数据中心的应用来持续的提供服务。
双活数据中心最大的特点是:一、充分利用资源,避免了一个数据中心常年处于闲置状态而造成浪费。通过资源整合,双活数据中心的服务能力是双倍的。二、双活数据中心如果断了一个数据中心,另外一个数据中心还在运行,对用户来说是不可感知的。
当前市场上常见的容灾模式可分为同城容灾、异地容灾、双活数据中心、两地三中心几种

  1. 同城容灾
    同城 容灾 是在同城或相近区域内 ( ≤ 200K M )建立两个数据中心 : 一个为数据中心,负责日常生产运行 ; 另一个为灾难备份中心,负责在灾难发生后的应用系统运行。同城灾难备份的数据中心与灾难备份中心的距离比较近,通信线路质量较好,比较容易实现数据的同步 复制 ,保证高度的数据完整性和数据零丢失。同城灾难备份一般用于防范火灾、建筑物破坏、供电故障、计算机系统及人为破坏引起的灾难。
  2. 异地容灾
    异地容灾主备中心之间的距离较远 (> 200KM ) , 因此一般采用异步镜像,会有少量的数据丢失。异地灾难备份不仅可以防范火灾、建筑物破坏等可能遇到的风险隐患,还能够防范战争、地震、水灾等风险。由于同城灾难备份和异地灾难备份各有所长,为达到最理想的防灾效果,数据中心应考虑采用同城和异地各建立一个灾难备份中心的方式解决。
    本地容灾是指在本地机房建立容灾系统,日常情况下可同时分担业务及管理系统的运行,并可切换运行;灾难情况下可在基本不丢失数据的情况下进行灾备应急切换,保持业务连续运行。与异地灾备模式相比较,本地双中心具有投资成本低、建设速度快、运维管理相对简单、可靠性更高等优点;异地灾备中心是指在异地建立一个备份的灾备中心,用于双中心的数据备份,当双中心出现自然灾害等原因而发生故障时,异地灾备中心可以用备份数据进行业务的恢复。
    本地机房的容灾主要是用于防范生产服务器发生的故障,异地灾备中心用于防范大规模区域性灾难。本地机房的容灾由于其与生产中心处于同一个机房,可通过局域网进行连接,因此数据复制和应用切换比较容易实现,可实现生产与灾备服务器之间数据的实时复制和应用的快速切换。异地灾备中心由于其与生产中心不在同一机房,灾备端与生产端连接的网络线路带宽和质量存在一定的限制,应用系统的切换也需要一定的时间,因此异地灾备中心可以实现在业务限定的时间内进行恢复和可容忍丢失范围内的数据恢复。
  3. 两地三中心
    结合近年国内出现的大范围自然灾害,以同城双中心加异地灾备中心的 “两地三中心”的灾备模式也随之出现,这一方案兼具高可用性和灾难备份的能力。
    同城双中心 是指在同城或邻近城市建立两个可独立承担关键系统运行的数据中心,双中心具备基本等同的业务处理能力并通过高速链路实时同步数据,日常情况下可同时分担业务及管理系统的运行,并可切换运行;灾难情况下可在基本不丢失数据的情况下进行灾备应急切换,保持业务连续运行。与异地灾备模式相比较,同城双中心具有投资成本低、建设速度快、运维管理相对简单、可靠性更高等优点。
    异地灾备中心 是指在异地的城市建立一个备份的灾备中心,用于双中心的数据备份,当双中心出现自然灾害等原因而发生故障时,异地灾备中心可以用备份数据进行业务的恢复。
    两地三中心 :是指同城双中心加异地灾备 一种商用容灾备份解决方案;
    两地 是指同城、异地;
    三中心 是指生产中心、同城容灾中心、异地容灾中心。( 生产中心、同城灾备中心、异地 灾备 中心 )
  4. 双活 数据中心
    所谓“双活”或“多活”数据中心,区别于传统数据中心和灾备中心的模式,前者多个或两个数据中心都处于运行当中,运行相同的应用,具备同样的数据,能够提供跨中心业务负载均衡运行能力,实现持续的应用可用性和灾难备份能力,所以称为“双活 ”和“多活 ”后者是 生产 数据中心投入运行,灾备数据中心处在不工作状态,只有当灾难发生时,生产数据中心瘫痪,灾备中心才启动。
    “ 双活 ” 数据中心最大的特点是 :一、充分利用资源,避免了一个数据中心常年处于闲置状态而造成浪费 , 通过资源整合,“ 双活 ”数据中心的服务能力是 翻 倍的 ; 二 、“ 双活 ”数据中心如果断了一个数据中心,其业务可以迅速切换到另外一个正在运行的数据中心,切换过程对用户来说是不可感知的。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值