zoukankan      html  css  js  c++  java
  • 读书笔记:《大型网站系统与Java中间件实践》

    大型网站演进

    在这里插入图片描述

    1. 单机扛不住 , 上集群
    2. 集群session问题
      1.hash(key)到固定的单机节点上,让其保持session
      如果一台web服务器故障,则会话丢失。需要登录。
      2.session复制
      将session复制到其他节点上。
      a.同步session增加网络带宽。
      b.增加内存消耗。
      3.session集中存储
      redis存储。
      好处:web之间没了session复制,也不保存在本机了。
      坏处:
      a.读写session引入了网络操作。
      不过一般是Redis在内网, 还好。
      b.存储session的机器有问题,则影响应用。
      4.Cookie Based
      相当于每次 都自带碗筷。
      a.cookie长度。
      b.安全性。
      不能信赖前端传来的数据,所以有加密解密。但是仍不安全。
      c.带宽消耗。

    数据库

    读问题

    数据库压力变大,读写分离
     1.数据库作为读库
     2.搜索引擎作为读库

    加速数据读取–缓存
     1.数据缓存
     2.页面缓存

    考虑局部热点的问题。
    扩容/缩容尽量平滑(一致性hash)
    定时失效、变更时失效、变更时更新

    写问题

    读写分离不能解决写(主库)问题
     1.专库专用,数据库垂直拆分
      交易、商品、用户数据分开。
      问题:引入了 分布式事务的问题。
    2.水平拆分
     数据水平拆分就是把同一个表的数据,拆分到多个数据库/表。
     问题:
      a.访问数据 引入路由(到不同库/表)
      b.主键处理,不能简单自增。
      c.分页出现问题。

    应用应对的挑战

    跟数据库拆分类似
     a.从业务垂直拆分
      订单、物流、商品、用户
     b.也可以水平扩容
      多台订单机器构建集群,抗下单压力

    引入服务层(service)
    引入消息中间件

    引入服务层框架:

    问题:网站规模扩大,开发人员增多,应用复杂、臃肿。
      解决方案:应用拆小。

    仍存在的问题:
      数据库连接数压力还在。
      系统之间存在重复代码。

    引入服务层:应用存在的问题 ,就继续抽象一层。
      将应用和底层数据库、缓存系统、文件系统等系统之间增加了服务层。可以理解成服务层处理简单、通用逻辑,并持久化到文件、数据库中。

    服务层的代表:dubbo
      应用直接调用有网络。
      利用动态代理+反射生成代理对象,帮助序列化,网络发送数据调用远程应用,并反序列化结果。隐藏细节。
    问题:
      服务者集群、调用者集群,如何路由。
    最初的路由寻址–找服务提供者
      1.透明代理:lvs,eureka
      2.从注册中心找地址,再直连

    基于服务提供者、接口、方法、参数来路由
      避免负载不均衡。

    多机房问题

    其他机房也被当做同一集群
     
    解决:
      1.根据调用者提供不同的服务者。
      2.框架内部进行地址过滤,识别机房。

    序列化与反序列化问题

    尽量短小(节省带宽)
      压缩与短小之间的平衡(cpu,网络)

    异步调用

    1.拆分没有前后依赖的服务,多线程异步调用。
      2.不需要结果的,异步调用。
      3.批量调用(类似mget)
      4.fork/join

    线程池隔离

    避免某个接口阻塞后,影响应用内其他接口。

    服务请求合并

    服务提供者避免重复计算。
      计算的时候加锁,其他线程再次访问则得到一个Future供之后获取结果。

    数据访问层

    数据拆分带来的影响:
    ACID
    路由
    join
    分页
    自增ID
    查询跨库

    一致性的基础理论–CAP/BASE

    希望强一致,但是代价太大,最终一致就好了。
     p:分区容忍性,系统部分有问题仍能运行。
     放弃C,保留AP。最终一致。

    如果强一致,单机。
     或者类似于ZK写入的时候,只要一半及以上同意就算写入成功。
     类似于MongoDB写入的时候,一半及以上replication接收即可。

    集群内数据一致性算法
     W+R>N 能保证强一致性
     W+R<=N可以保证最终一致性

    分布式事务,考虑最终一致即可。
     实现上来说通过补偿不断重试,而不是回滚。
     或者TCC 应用层自行做抵消操作。
     两者可以合并
      TCC+人工补偿

    多机的Sequence问题

    水平分库后,自增ID还是要保证:
    唯一性
    连续性

    唯一性:
    uuid
    连续性:
     1.单独做一个id自增的管理器。
      性能降低。
      需要灾备保证稳定。
     2.应用指定ID段

    扩库join
     1.多次查询。
     2.数据冗余到单表上,避免join.

    排序后分页
     1.考虑到所有数据可能都来自 一个数据源,所以分页的时候在一个源中取足(size条)数据。
     2.将所有数据源的数据组合排序,再取前size条。

    消息中间件

    功能

    削峰削谷:
      平滑处理消息。
    异步:
      快速返回。
    解耦:
      应用直接没有直接联系,方便接入

    消息一致性

    jms通过XA解决

    分阶段-多次消息投递
     业务先发送到消息中间件标记为待处理。
     之后处理完业务后再发送到消息中间件,标记为成功。(消息投递)
    不断补偿-最终一致

    避免对消息中间件的强依赖

    避免消息中间件挂掉后影响业务:
     1.业务应用 将操作和需要入队的消息 作为一个事务,保证消息写到【本地消息表】中。–一个事务保证完成。
     2. 消息中间件/应用 轮询 本地消息表去获取消息,投递到消息中间件中即可。–最终可靠

    级联、嵌套topic/queue

    消息发送到中间件的可靠性保证(发送可靠)

    持久订阅、非持久订阅
     
     消息中间件返回成功才认为 可靠消息到达中间件了,否则重发。
     
     消息持久化到数据库、文件。

    消息投递的可靠性保证(消费可靠)

    得到消息,并处理成功才向 消息中间件 返回成功
     业务没处理完不能去确认消息(ack)
    可能业务处理成功,但ack发送失败,导致以为失败
     业务继续补偿,但是幂等。直接ack,删除消息中间件的消息。

    消息者重复消费

    1.重复发送到消息中心。
     消息标记ID,同一ID无法重复发送。
    2.应用端重复接收消息中心的消息。
     应用端进行幂等操作。

    避免投递线程被阻塞

    1.接受消息与处理消息分开。(类似于select+handler的boss线程与worker线程)
    2.线程池。

    《大型网站系统与Java中间件实践》

  • 相关阅读:
    【Nodejs】cheerio简单示例
    【复习】请求转发与请求重定向的区别:
    常用的 default.properties 文件 + 常用的 struts-default.xml 文件 + 常用的 struts-plugin.xml 文件 + 常用的 struts.xml 文件 + 常用的 struts.properties文件 + 常用的 web.xml 文件
    log4j WARN 的解决办法
    Caused by: 元素类型为 "package" 的内容必须匹配 "(result-types?,interceptors?,default-interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-mappings?,action*)"。
    Myeclipse2017无法修改项目的Web Context Root问题
    springMVC的注解@RequestParam与@PathVariable的区别
    easyUI的控件
    easyui datagrid json 格式
    java泛型中<?>和<T>有什么区别?
  • 原文地址:https://www.cnblogs.com/thewindkee/p/12873108.html
Copyright © 2011-2022 走看看