大型网站系统与JAVA中间件学习 - Go语言中文社区

大型网站系统与JAVA中间件学习


定义:中间件不是操作系统的一部分,不是数据库管理系统,也不是软件应用的一部分,而是能够让软件开发者方便地处理通信,输入输出,能够专注在他们自己的应用部分。相当于桥梁。
远程过程调用和对象访问中间件:主要解决分布式环境下应用的相互访问问题。
消息中间件:解决应用之间的消息传递,解耦,异步的问题。
数据访问中间件:主要解决应用访问数据库的共性问题的组件。

数据库访问层:
数据库优化有三个层次
1.优化应用;2.引入缓存,加收索引擎;3.数据库的数据和访问分到多台数据库上
数据拆分方式:1、水平拆分:根据一定的规则把同一业务的数据分到不同的数据库中。2、垂直拆分:一个数据库中不同业务单元的数据分到不同的数据库中。
垂直拆分的影响:1.单机的AICD被打破。2.一些join操作变得复杂。3.靠外键约束的场景受到影响。
水平拆分的影响:1.ACID被打破;2.Join操作变得复杂。3…靠外键约束的场景受到影响。4. 依赖主键唯一增加受到影响。5.针对单个逻辑意义的表查询要跨库。
分布式事物的:CAP原则。只能满足其中两个原则。C:一致性;A:系统有反馈,可用性。P:系统分区容忍性。
一般选择AP,放弃一致性。
BASE模型:1.基本可以,允许分区失败。2.软状态,接收一段时间的状态不同步。3.最终一致性,保证最终数据的状态不一致。

集群内数据一致性的算法:
N:数据复制节点数量;R:成功读操作的最小节点数;W:成功写操作的最小节点数
W+R>N 保证强一致性;W+R<=N 保证最终一致性。

多机的sequence问题和处理
数据库水平拆分后,原数据库中的sequence以及自增id的做法需要改变。
唯一性,连续性。
如何实现连续性:将id集中放在一个地方进行管理,每个id序列独立管理,每台机器使用ID时都从这个id生成器上取。
性能问题:每次远程取id都会消耗资源。
生成器稳定性问题:id生成器作为一个无状态的集群存在,其可用性要靠整个集群来保证。
存储问题:
解决方法:1.应用通过统一的id生成器。2.每个机器有自己的id生成器,这种方法比较复杂。
应用多机的数据查询
水平分库:可以按照地域进行数据库的划分,这样每个用户根据所在地就可以查询出信息。
复杂的情况:1.排序:即多个来源的数据查询出来后,在应用层进行排序。多路归并排序。2.函数处理:即使用Max,Min等函数对多个数据源的值进行函数处理。3.求平均值:从多个数据来源进行查询时,将多个数据进行求和。4. 非排序分页,同等步长:分页的每页中,来自不同数据源的记录数是一样的;同等比例:来自不同数据的数据源所占的比例是一样的。5.排序后分页:最为复杂的情况。
对我提供数据库访问层的功能

  1. 为用户提供专用API,通用性很差。
  2. 通用的方式,采用JDBC方式访问数据库。
  3. 基于ORM或者ORM接口的方式,类似于mybatis。

数据层流程看数据库设计:
这里写图片描述

消息中间件
消息中间件的主要作用是解耦。
举例:用户登录成功后发送消息,确保消息发送到消息中间件。
方法(不太好的方法):1. 在数据库中记录状态,这样增大了数据库访问的压力。
2. 依赖的复杂和不安全。使得发送短信的服务依赖业务数据库。
3. 扩展性不好。

互联网消息中间件的价值:消息中间件使用的的规范JMS,activeMq是对这个产品规范的实现。中小型适合,大型不适合JMS。
如何解决消息发送的一致性
消息一致性的定义:产生消息的业务动作与消息发送是一致的。如果业务成功了,这个操作的消息发送出去了。如果业务失败,则这个消息不能发送出去。
举例:2种方法。

void foo1(){
//业务操作
//调用服务,写数据库
//发送消息
}

问题可能是消息系统挂掉,导致消息发送不出去。

void foo2(){
//发送消息
//业务操作
//调用服务,写数据库
}

这种方式更差。

JMS:
这里写图片描述
这里写图片描述
这里写图片描述
在JMS中存在XA开头的接口,其实就是支持XA协议的接口。
这里写图片描述
在JMS中不使用XA系列的接口,就无法得到发送消息给消息中间件及业务操作这两个事件的事物保证。而JMS中定义的XA的接口是为了实现分布式事物的支持(发送消息和业务操作很难做在一个本地事物中。)带来的问题
1. 引发分布式事物,带来开销并增加复杂性。
2. 业务操作有限制,要求业务操作的资源必须支持XA协议,才能够与发送消息一起做分布式事物。
消息一致性的解决方案:
这里写图片描述
这里写图片描述
这里写图片描述
对可能的异常进行分析:

  1. 业务应用发送消息给消息中间件。这一步失败,结果一致。
  2. 消息中间件把消息入库,这一步失败。操作2个结果:一个消息中间件失效,业务收不到消息中间件返回的结果;二是消息中间件插入消息失败,返回结果给应用。结果最终一致。
    1. 业务应用收到消息中间件返回结果异常。异常可能是网络、消息中间件问题,业务应用自身问题。如果业务自身没有问题,那么业务应用并不知道消息中间件的处理结果,按消息失败处理,这时候如果消息入库,会造成不一致;如果应用有问题,消息中间件成功也会造成不一致。
  3. 业务应用进行业务操作,这一步不会产生太大问题。
  4. 业务应用应用发送业务操作结果给消息中间件。这一步会造成不一致。
  5. 消息中间件更新状态,造成结果不一致。
    这里写图片描述
    这里写图片描述
    通过分析 :我们遇到的状态分为3种。
  6. 业务操作未进行,消息未入存储。
  7. 业务未进行,消息存储,状态为待处理
  8. 业务操作成功,消息存储,状态为待处理。
    需要处理的状态为2,3。下图展示消息 中间件主动询问业务应用,反向流程。
    这里写图片描述
    这个流程主要是第4步可能出现异常,反复定时这个反向流程可以解决问题。
    这里写图片描述

如何解决消息中间件与使用者的强依赖问题
方法:1. 提供消息中间件系统的可靠性。
2. 对于消息中间件系统中影响业务操作进行的部分,使其可靠性与业务自身的可靠性相同。
3. 提供弱依赖支持,能够较好的保证一致性。
第二种方案:让消息中间件系统中影响业务操作的部分与业务自身具有同样的可靠性,保证业务能够操作成功。
这里写图片描述
这样产生的影响是:1. 需要业务自己的数据库承载消息数据。
2. 需要消息中间件去访问业务数据库
3. 需要业务操作的对象是一个数据库,或者支持事物的存储。
这里写图片描述
这里写图片描述
消息队列接收方式:queue;topic。
JMS中客户端连接的处理和带来的限制:每个 connection中有唯一的clientId,用于标记连接的唯一性。我们默认一个接收应用只用一个连接。
需求:1. 消息接收方和发送方都是集群。
2. 同一个消息的接收方可能有多个集群进行消息的处理。
3. 不同集群对于同一条消息的处理不能相互干扰。

对于集群消息,采用单独采用queue或者topic都不满足要求。原因:单独的queue,消息可能被其他集群消费;采用topic消息可能被同一集群的相同应用重复消费。这时候应该采用虚拟分组。
具体是集群和集群之间采用topic模型处理,集群内部采用各个具体实例对消费者单独当做queue来使用。这里引入clusterId,通过这个id标识集群,集群内的实例使用相同的clusterId。
这里写图片描述
如果非要使用JMS采用下面的方法:
这里写图片描述

消息的订阅:
消息订阅分为持久订阅和非持久订阅:
持久订阅:消息接受者停止运行,还可以接收到这两天消息。消息订阅关系一旦建立,出发显示的取消否则订阅关系一直存在。
非持久订阅:消息停止后,可能丢失掉某些消息。
如何保证消息持久订阅:1. 消息发送者将消息发送给消息中间件;2. 消息中间件把消息存入消息存储;3. 消息中间件把消息投递给消息接受者。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_23211905/article/details/73863186
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-25 00:30:41
  • 阅读 ( 946 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢