ROS交流群
ROS Group
产品服务
Product Service
开源代码库
Github
官网
Official website
技术交流
Technological exchanges
激光雷达
LIDAR
ROS教程
ROS Tourials
深度学习
Deep Learning
机器视觉
Computer Vision

分布式程序数据同步问题分析



  • 对于分布式程序,甚至更一般的并行式程序,数据同步都是一个很头疼的问题。首先分析一下为什么这个问题很头疼。
    对于一般的并行程序,在一个线程读取数据的时候,别的线程不能对同一个数据进行修改。否则就会导致数据不一致。所以一般的方法是加锁。在读取数据前先申请数据的锁,读取前把数据锁住,不让别人更改。读取完成后再释放这个锁。同样写入也是一样的。这样就保证了读取和写入不会同时发生。对于分布式程序,虽然原理上差不多,但是情况要复杂很多。首先是节点本身不稳定。随时都有节点加入和退出网络。可能一个节点正在操作关键数据,接着就意外掉线了。其次还有效率的问题,数据的更改最终一定会传遍整个网络。采用什么样的策略去传递更改直接影响网络的效率。如果采用独占锁的方式,那么在一个节点访问数据到时候,其他节点的资源实际上是一种浪费。如何避免这些问题呢?这都是同步算法所要考虑的。

    这里就总结一下我所看到的数据同步方法。

    1. Ceph的主节点同步法
      Ceph是一种分布式文件存储程序。这个算法就是其中的文件同步算法。Ceph的节点具有动态性。也就是说随时都有节点的加入和退出发生。所以相对于MIT的算法应用环境要更广。
      算法的主要过程如下。首先节点分为控制节点和内容节点。控制节点监控所有内容节点的状态。比如是不是掉线了,是不是出现读写错误了。并且维护一份当前内容节点的列表。列表的第一个有效内容节点作为主内容节点。如果这个节点掉线,就依次往下找。所以在同一时刻内会有唯一的一个主节点。所有的写入操作只能发生在主节点。主节点写入完成后向其他节点扩散更改。当所有更改完成后主节点通知客户端写入完成。这里可以看出来主节点的负担相对要重很多。

    2. Mit的Cpu同步法
      首先说一下这种算法的应用环境特点。这个算法是我在MIT News里面看到的。是MIT研究出的用处多核处理器各核之间数据同步的算法。所以是应用在处理器中的。这样就保证了节点的结构是稳定的,不会突然有节点掉线之类的问题。
      这个算法和Ceph的主节点法比较类似。但是主节点是动态的。每一个核相当于一个节点。每个核都有自己的数据缓存。每份数据都有一个主节点。当某个核想要更改数据的时候先要通知当前的主节点,自己想要成为主节点。主节点确认数据是最新的后,这个核就成为新的主节点可以开始更新数据了。(这个算法我不太确定和原文是不是一致,我找不到原文了)

    3. Zeronet的随机同步法
      ZeroNet是一个分布式网站程序。这个是算法就是其中的同步算法。由于作者设计的时候并不要求严格的数据一致性。所以这个算法也比较简单。每个节点都可以对数据进行更改。更改后把更改后的文件对随机的几个和自己相连的节点进行广播。同时在更改上标记上更改发生的时间。其他节点接收到这个更改的时候。把更改和自己当前的文件进行比较。如果更改比自己的文件要新,就用更改后的文件替换自己当前的文件。同时继续把更改推送到随机的几个和自己相连的节点。反之如果更改没有自己当前的文件新。就把自己的文件推送给发给自己这个更改的节点。
      这种算法很容易出现数据丢失和错误的情况。比如A节点先对文件进行了更改。在A的更改同步到所有节点之前。B节点也对文件进行了更改。这样B的更改就会把A的更改覆盖掉。导致A更改的数据丢失。但是对于网页中的评论这样的应用来说,少一两条评论也是无所谓的事情。同时由于指数式扩散和简单的原则,这个的效率应该是不错的。

    4. 我的mongomanager同步法
      这个是我用在mongodb分布式数据库中的算法。算是从上面的几种算法里面变出来的吧。网络节点也是不稳定的。有节点加入和退出网络发生。就目前使用情况来说还不错。
      基本结构由控制节点和客户端节点组成。所有的客户端节点都和控制节点相连。控制节点选取其中一个客户端节点作为主节点。主节点保存着最新的数据库数据。如果某一个客户端节点想要更改数据库,那么它就要先向控制节点申请成为主节点。控制节点把这个节点和当前主节点进行比较。如果此节点已经同步到最新数据就把当前主节点设置成这个节点。成为主节点后这个节点就可以进行数据库操作了。此时所有的数据库更改操作都会被推送到控制节点,由控制节点向其他节点进行广播。其他节点收到请求后执行相应的数据库操作。由此保证各个节点的数据同步。
      实际上目前没有完全的做到去中心化。因为控制节点是固定的。当然也可以改成控制节点也是动态的。这种算法保证读取数据一定是正确地,但不一定是最新的。就好像看网页一样。你用浏览器打开的网页可能不是现在最新的网页,但一定是曾经出现的。刷新一下才能确定获得最新的页面。