《设计数据密集型应用/DDIA》精要翻译(六) :分布式系统中的问题

这一章我们会讨论分布式系统中一些常见的问题,在下一章中我们会讨论这些问题的解决办法。

1.故障与部分失败

在分布式系统中,系统的部分组件常常会以以某种未知的方式被破坏,我们称之为部分失败/部分故障。而我们的目标就是在不可靠的组件上构建一个可靠的系统。

为了容忍部分失败:

  • 第一步是检测失败:大多数系统利用超时来判断节点是否可用,但是超时机制没办法区分是网络失效还是节点宕机
  • 在检测到失败之后,如何使系统去容忍失败也是个大问题:节点间通信的唯一方法是通过不可靠的网络发送信息,不能由一个节点来做决策,因此我们需要一致性协议算法来帮助我们完成这个目标。

2.不可靠的网络

在分布式系统中,节点与节点间的网络通信是不可靠的,它表现在:

  • 网络分区:网络的一部分发生了故障而被切断
  • 延迟问题:TCP协议虽然提供了数据校验、超时重传等机制,但是没办法保证数据包在一定时间内保证到达,这种延迟可能是无限的。

3.不可靠的时钟

在分布式系统中,时钟是一个非常重要且棘手的问题:

  • 节点与节点间的通信是有延迟的,我们很难确定多个节点间事件的顺序问题
  • 每台机器都有自己的时钟(硬件设备),这些设备不都是完全准确的

时钟分为两种,单调时钟与Time-of-Day时钟:

  • 单调时钟一般用于计算持续时间,如Java中的System.nanoTime()
  • Time-of-Day时钟根据某个日历返回当前的日期和时间,一般依赖于NTP服务器或其他外部时间源
时钟不同步导致的问题

时钟的不同步会导致很多问题,比如前面的博客中,我们谈到多主备份数据库解决写入冲突的一个常见办法是LWW,即最后写入者胜出,在时钟不同步的情况下可能会导致如下问题:

ClientA在node1上写入x=1,并同步到node3。 ClientB在node3上写入x=x+1,也同步到node2。但是B的写入同步比A的更早到达,从而导致在node2上x+1的操作消失了。

进程的暂停问题

假设在一个分布式数据库中,节点通过选举方式成为leader(只有leader能接受写请求),并获得一个租约,且同一时间只有一个节点能获得租约。假设有这么一段代码:

while (true) {
     request = getIncomingRequest();
     // Ensure that the lease always has at least 10 seconds remaining
     if (lease.expiryTimeMillis - System.currentTimeMillis() < 10000) {   
         lease = lease.renew();
      }
     if (lease.isValid()) { 
         process(request);
     }
}

这段代码的问题:

如果当前线程在lease.isValid()之后暂停了15秒,然后才继续运行process(request),而这时候租约可能已经到期了,它已经不再是leader了!

那么这个进程为什么要暂停这么久呢? 可能的原因如下:

  • GC运行了很久
  • 虚拟机被挂起,当前所有进程被暂停并把内存内容保存到磁盘
  • 进程接收到了SIGSTOP信号,暂停使用CPU周期;之后又接收到SIGCONT信号才恢复
  • 执行了同步访问磁盘的操作,如果磁盘需要走网络(比如EBS),可能延迟很大
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值