分布式设计

2019-07-24 09:17:14来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

分布式设计

  • 1.复制
  • 作用
    • 对数据备份,实现高可用
    • 提高吞吐量,实现高性能
  • 分类
    • 主从架构
      • 性能
        • 一主多从,读写分离,提高吞吐量
      • 可用性
        • 主库单点,一旦挂了,无法写入
        • 从库高可用
      • 一致性
        • 数据同步存在延迟,读时从库中返回的可能是旧数据
          • 解决方案
            • 直接忽略,存在延迟很正常
            • 班不同步复制(semi-sync),主从同步完成写请求才返回,吞吐量降低
            • 选择读主
              • 思路
                • 写操作时,根据库+表+业务特征生成key设置到缓存中并设置超时时间(大于等于主从数据同步时间),读操作时,同样方式生成key,先去查缓存,如果命中则读主库,否则读从库
              • 技术难点
                • 主从数据同步时间的计算 不同网络,配置下,时间不一样
              • 很多数据库的中间件就是使用的这种思路,如mycat等,但是中间件的成本同样不低
            • 对于即时性有要求的接口,直接从主数据库读
        • 读写分离的情况下,并发出现更新丢失问题
          • 悲观锁
            • 必须加载主数据库商,这样就不能做读写分离
          • 乐观锁
            • 可以
            • update当前读,这样也不能做读写分离
          • 有一致性要求的接口,无法读写分离,只能从主库中操作
    • 多主架构(互为备份)
      • 性能
        • 负载均衡
      • 可用性
        • 高可用
      • 一致性
        • 和主从架构一样
    • 主主从从
      • 高性能
      • 高可用
      • 一致性
        • 和主从一样
    • 主备
      • 主库提供读写服务,备库做故障转移用
      • 性能一般
        • 提高性能 设置缓存
      • 高可用
      • 无一致性问题
      • 使用广泛 58和阿里云
  • mysql主从同步的原理
  • 2.分片/分库分表
  • 需求分析
    • 用户请求量太大 -> 分布式服务器(分散请求到多个服务器上)
    • 单库太大  单库所在服务器上磁盘空间不足;处理能力有限;出现IO瓶颈
    • 单表太大 -> CRUD都成问题,索引膨胀,查询超时
  • 作用
    • 共同组成完整的数据集合,扩充单机存储的容量上限,读写速度上限
  • 每个服务器节点成为分片
  • 优点: 高吞吐
    • 吞吐量越高,同一时间数据的读写完成量越高
    • 一个节点可能单日吞吐量只能到达1TB(收硬件限制,硬盘速度有限)
  • 垂直拆分
    • 垂直分表
      • 把字段分开成多张表
    • 垂直分库
      • 将有关联的表放在一个数据库中 如用户表,用户频道表等
    • 项目处理
      • 用户数据垂直分表  user_basic  user_profile
      • 文章数据垂直分表(文章内容较长且只在详情页才需要) article_basic  article_content
        • 两张表 定义时都包含其关联数据,这就要求使用事务来保证数据一致性
  • 水平拆分
    • 水平分表
      • 将1000万条记录分成两张表
      • 分表方式:按时间/id/地理/hash取模 分表
    • 水平分库分表 分表分别放在不同的节点,使用率极高
    • 分布式ID
      • 需求:水平分表后,需要保证多表id不会出现冲突
      • 解决方案
        • UUID 通用唯一识别码 缺点:较长,不会趋势递增(主键如果不是递增的,索引效率会比较低)
        • 数据库主键自增
          • 方案1: 单独数据库 只负责生成主键  缺点:一旦宕机,全局瘫痪
          • 方案2: 设置自增步长 所有表都使用相同的步长 缺点:分片规则不能修改,无法扩展
        • Redis
          • incr("user_id")返回的值自增
          • 不会出现资源抢夺问题,因为redis是单线程的,可以保证原子性
          • 缺点
            • redis宕机
            • redis易数据丢失
        • 雪花算法-Snowflake
          • twitter提出的算法,目的是生成一个64位的整数

          • 缺点:时间回拨,及其的原因时间可能出现偏差,虽然会同步进行校正,但生成时可能是错误的
            • 如果发生回拨(当前时间<记录的时间),算法会自动抛出异常,可以让用户稍等一会儿
            • 取消同步ntp时间
          • 项目中的应用
            • 用户id 文章id 评论id 后期数据量可能会很大
    • 前期数据量和请求次数少时,不要做分片
  • 分布式问题
    • 一致性问题
      • 主从延迟
        • 对于即时性高的接口,直接从主库中提取
      • 更新丢失
        • 不进行读写分离,在主库中完成流程
    • 分片id冲突
      • 实现分布式ID
    • 跨库原子性
      • 一个业务中可能包含多个库中的写操作,该业务需要具有原子性,但是无不具备跨库原子性
      • 解决办法
        • 将有关联的表放在一个数据库中
        • 使用分布式事务
          • 核心是二阶段提交协议(简称 2PC协议/XA协议)
          • 会出现事务等待的情况,增加死锁的产生机率,效率低
        • 通过优化业务逻辑,实现基于消息的最终一致性方案(本质是通过消息队列执行异步任务,部分失败则不断重试/或全部取消,一般需要中间件完成任务分发,任务充实,消息幂等等)
          • 分布式中间件 merge引擎 分库分表中间件 mycat
    • 跨库join
      • join不允许跨库完成
      • 解决办法
        • 分两次查询进行
        • 开启FEDERATED引擎
    • 跨库结果集 聚合/排序/分组
      • 不允许跨库操作
      • 分别查询,然后再应用端合并
    • 项目中的处理
      • 复制
        • 采用了主从架构,实现了"手动读写分离",但没有对主从延迟进行特殊处理
      • 分片
        • 实现了垂直分表
        • 使用了雪花算法生成了分布式ID,为水平分表提供了准备(单表行数至少超过1000万)
        • 由于垂直分表后没有分库,所以没有(不需要)实现分布式事务(所有写操作都在一个主库中)
      • 没有使用分布式中间件
    • 应用层设计方案
      • 悲观锁
        • 开发者主动设置锁
      • 乐观锁
        • 先不加锁(假设不会有并发问题),但是更新前校验数据一致性,需要手动代码实现
        • Django项目中先判断库存,再生成订单,就是乐观锁设计
        • 高级的乐观锁可能会采用版本号/时间戳来校验,需要进行表设计
        • 1 读取点赞数,如like_count=10
          2 每次更新表中的数据时,为了防止发生冲突,需要这样操作
          3 update t_article set like_count = 11 where article_id = 5 and like_count = 10;

           


原文链接:https://www.cnblogs.com/Infernal/p/11158076.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Django框架深入了解_05 (Django中的缓存、Django解决跨域流程(非

下一篇:HTTP: Request中的post和get区别