草庐IT

c++ - 内部分布式时间服务器实现

coder 2024-02-04 原文

我为我们即将推出的分布式 NoSQL 数据库系统制作了一个内部分布式时间服务器(没有主服务器)。只要分布式系统中 2/3 的时钟是正确的,它就应该处理拜占庭时钟和时钟偏差问题。

不过,我想看看其他人是如何实现这种模式的(对基于 IEEE 1588 的主/从模式实现不感兴趣)——最好是一些已经在使用的开源代码——以断言我已经正确实现它,因为很难为它编写单元测试。

有人知道这样的开源实现吗?我们使用 C++ 的编程语言,所以我更喜欢 C/C++ 引用,尽管它可能不是那么重要,只要代码是人类可读的。

这是我到目前为止的实现代码(为简单起见,部分伪代码):

/*!
\brief Maximum allowed clock skew in milliseconds
\details A network node that has a clock skew greater than this value will be ignore
* and an error message will be logged
\note Maximum divergence (drift) between two clocks on the network nodes will be 3x this amount if we 
* have a worst case Byzantium clock issue
*/
#define MAX_ALLOWED_CLOCK_SCEW_MS 333

/*!
\class CTimeServer
\brief Internal distributed time server
\details The time server frequently recieves the time from all the other master server nodes
* in the DBMS and calculates the current time by averaging all of the recieves timestamps.
\note If a server node has a greater clock skew than \c MAX_ALLOWED_CLOCK_SCEW_MS then it its
* timestamp is ignored and an error message is logged
\note Clocks are accurately synchronized until more than 1/3 of the nodes have Byzantium clock issues
\author Inge Eivind Henriksen
\date February 2014
*/
class CTimeServer
{
    private:
        /** System offset in milliseconds */
        std::atomic<int> offsetAverageMs;

        /*!
        \brief Node offsets type
        \par key Node ID
        \par value Offset in milliseconds
        */
        typedef std::map<int, int> nodeOffset_t;

        /*!
        \brief Iterator type for \c nodeOffset_t
        \relates nodeOffset_t
        */
        typedef nodeOffset_t::iterator nodeOffsetIter_t;

        /** Node offsets */
        nodeOffset_t nodeOffsets;

        /*!
        \brief Calculates the offset time in milliseconds between all the nodes in the distributed system
        */
        int CalculateOffsetMs() {
            bool exists;
            nodeOffsetIter_t offsets_iter(&nodeOffsets);
            int offsetMs = offsets_iter.first(&exists);
            int averageMs = 0;

            while (exists)
            {
                averageMs += offsetMs;
                averageMs /= 2;

                // Get the next file manager in the map
                offsetMs = offsets_iter.next(&exists);
            }

            return averageMs;
        }
    public:
        CTimeServer() {
            offsetAverageMs = 0;
        }

        /*!
        \brief Register the time of a node
        \param nodeHostName [in] Network node host name or IP address
        \param nodeId [in] Network node ID
        \param timestamp [in] Network node timestamp
        */
        void RegisterNodeTime(const wchar_t *nodeHostName, int nodeId, time_t timestamp) {
            int now = (int)time(NULL);
            int offset = (int)timestamp - now;

            // Make sure the node clock is within the permitted values
            if (abs(offset) > MAX_ALLOWED_CLOCK_SCEW_MS)
            {
                // Node clock skew was outside the permitted limit, so remove it from the list of valid time offsets
                nodeOffsets.erase(nodeId);

                // Throw an error
                std::wstringstream err;
                err << L"Network node " << nodeHostName << L" exceeded the maximum allowed clock skew of " 
                    << MAX_ALLOWED_CLOCK_SCEW_MS << L" ms by " << offset << " ms. Set the clock to correct this problem.";
                throw err.str().c_str();
            }

            nodeOffsets.update(nodeId, offset);

            // Recalculate the offset average
            offsetAverageMs.store(CalculateOffsetMs());
        }

        /*!
        \brief Get the distributed system time
        \returns The distributed system time
        */
        time_t GetTime() {
            int now = (int)time(NULL);
            return (time_t)(now + offsetAverageMs.load()));
        }

最佳答案

有大量关于时间同步协议(protocol)的文献,特别是对于无线传感器网络,其部署环境不适合时间掌握者。在 this page 上对该主题有一个不错的介绍。 .似乎最受关注的协议(protocol)是泛洪时间同步协议(protocol) (FTSP),来自 paper。 Maróti、Kusy、Simon 和 Lédeczi 以这个名字命名。我在其 wiki 上找到了一个针对 TinyOS 的实现。 ,其中包含您正在寻找的代码类型。

对于任何无主系统都有一个警告:没有“正确”时间的概念。您可以获得的最好结果是将节点收敛到一个公共(public)时间引用。这是一个共识时间,但不应被视为权威的“正确”时间。

关于c++ - 内部分布式时间服务器实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22065401/

有关c++ - 内部分布式时间服务器实现的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  7. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  8. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  9. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  10. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

随机推荐