不同服务器之间的数据同步(skynet 和 c++)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不同服务器之间的数据同步(skynet 和 c++)相关的知识,希望对你有一定的参考价值。

参考技术A

最近公司开发了一个捕鱼游戏,现在想要把这个项目嵌入到公司已有的游戏中,成为其子游戏,开发捕鱼的服务器框架是基于 skynet 的框架(独立一套系统)。而已有的游戏服务器框架是c++自研框架(也是独立的一套系统),所以需要解决一个问题:就是两个系统中数据共享的问题,因为用户都是现有游戏中的。捕鱼并没有用户,用户从主游戏中进入到捕鱼势必要把 ta 的金币、钻石、道具等数据带到捕鱼服务器,最终用户退出捕鱼游戏,要把用户现在的金币和其他数据移动回去,这里就涉及到数据共享和维护数据唯一性的问题了。

最初的方案是选择 http 请求通知的方式进行通信。但是考虑到极端情况: 如高并发,如果一秒钟发起 2W 次请求那么以 http 的处理方式就是要 每秒建立tcp链接和断开链接 * 2W次,文件描述符占用、和不能便捷集成到两个系统业务层中、以及网络异常处理需要依赖到DB保存数据待后续恢复、以及后续的集群部署需要再做考虑,等等这些缺点都是无法忍受的。

后面考虑用 redis 的 Pub/Sub 来实现高效的 MQ 并且在请求发起的时候如果超时,如果数据是必须被对方接收的话,还可以直接把数据写入缓存,让对端自行获取。遂和其他 xxMQ 进行对比,最后不管从易用性、通用性、高可用等等方面上都是 redis 胜出,当然 redis 的 Pub/Sub 也是有缺点的,但是使用到上述的这个应用场景来说,都是可以忽略的。

数据一致性保证机制
如果发起端请求对端超时 会将请求的数据写入到缓存,其格式如下:
保存到 redis 中的类型:set
key: 捕鱼缩写(f) + "_" + 用户uid
value: "请求的命令 "+" @ " + [ k + "|" + value [ k + "|" + value ...] ]

实例 key = f_10001 value = req_mv_gold@gold=10000|session=1
含义为:捕鱼发起的请求(f) 用户uid(10001) 命令(req_mv_gold)和携带数据用 "@" 分割,数据中字段与字段用 "|" 进行分割。数据解析,按对应命令协议定义结构进行解析。

1.用户登录了捕鱼,进入捕鱼游戏,用户向斗地主发起请求 req_mv_gold 数据中 gold 字段值为 0,斗地主就把用户的金币先保存到临时变量,然后置空用户的金币,再把用户金币通过 rsp_mv_gold 发送给捕鱼,如果 rsp_mv_gold 没有收到响应,斗地主要把钱加回给用户,意味这一次转移金币失败

2.假如用户已经成功完成了上面的步骤,此时用户在斗地主中的金币值为 0,在捕鱼中的金币值为用户实际金币值。

3.等用户退出捕鱼游戏就再次向斗地主发起第一个步骤的请求,如果成功,则完成了金币转移,如果失败(可能斗地主服务器中,这个用户下线了,可能斗地主奔溃了,可能网络阻塞或者掉线),捕鱼会把这次的请求写入到 redis 中,也就是上面的这个例子。

4.用户再次登录斗地主时,斗地主服务器需要去redis中查看是否有 捕鱼缩写(f) + " " + 用户uid 的这个健的存在,如果存在了,就要读取该键全部的成员
如:SMEMBERS f_10001,(理论上来说,每种请求最多一条记录)并且删除掉 redis中的 捕鱼缩写(f)+"
"+uid 的健 如:DEL f_10001。并且按具体内容恢复数据。

这个机制适用于全部需要确保对端收到的命令。如果对端是捕鱼,那么 set 的键是 斗地主缩写(d) + "_" + uid,表示斗地主发起的请求失败了,捕鱼会按上面的流程自行处理。

在两个不同的程序之间发送/接收数据

【中文标题】在两个不同的程序之间发送/接收数据【英文标题】:Sending/Receiving data between two different programs 【发布时间】:2013-12-30 12:50:29 【问题描述】:

我主要在这里寻求一些建议。

我正在开发一个应用程序,其中主要处理(存储在服务器上)是在 C++ 中执行的,而 GUI(前端)是在 Python 中执行的。这两个程序将相互通信。 Python 将发送 C++ 程序运行所需的文件,并为 C++ 程序提供一些可使用的数据。然后后端将与处理后的数据进行通信。

因此使用套接字会更好吗?我曾考虑使用文本文件完成此操作,但是,已经放弃了这个想法,而是将数据保存为 .txt 文件,以便在将来的实例中打开它。另外,如果我使用sockets,使用Python/C++会不会有冲突?

任何帮助或建议将不胜感激。

【问题讨论】:

您是在向服务器发送文件,还是通过文件来表示数据? @RaydelMiranda 文件将是 .wav 文件,服务器会将数据作为双精度发送回,但不是作为文件.. 如果这样有意义吗? 但是客户端(Python)发送文件对吗? @RaydelMiranda 是的,抱歉,客户端会将 .wav 文件从其桌面发送到服务器。 =) 【参考方案1】:

试试ZeroMQ

ØMQ(也称为 ZeroMQ、0MQ 或 zmq)看起来像一个可嵌入的 网络库,但就像一个并发框架。它给你 跨各种传输传输原子消息的套接字,例如 进程内、进程间、TCP 和多播。您可以连接套接字 N-to-N 模式,如扇出、发布-订阅、任务分配和 请求-回复。它的速度足以成为集群的结构 产品。它的异步 I/O 模型为您提供可扩展的多核 应用程序,构建为异步消息处理任务。它有一个 语言 API 的分数并在大多数操作系统上运行。 ØMQ 来自 iMatix 并且是 LGPLv3 开源。

C++ Hello world 服务器:

//
//  Hello World server in C++
//  Binds REP socket to tcp://*:5555
//  Expects "Hello" from client, replies with "World"
//
#include <zmq.hpp>
#include <string>
#include <iostream>
#ifndef _WIN32
#include <unistd.h>
#else
#include <windows.h>
#endif

int main () 
    //  Prepare our context and socket
    zmq::context_t context (1);
    zmq::socket_t socket (context, ZMQ_REP);
    socket.bind ("tcp://*:5555");

    while (true) 
        zmq::message_t request;

        //  Wait for next request from client
        socket.recv (&request);
        std::cout << "Received Hello" << std::endl;

        //  Do some 'work'
#ifndef _WIN32
        sleep(1);
#else
    Sleep (1);
#endif

        //  Send reply back to client
        zmq::message_t reply (5);
        memcpy ((void *) reply.data (), "World", 5);
        socket.send (reply);
    
    return 0;

Python 客户端:

#
#   Hello World client in Python
#   Connects REQ socket to tcp://localhost:5555
#   Sends "Hello" to server, expects "World" back
#
import zmq

context = zmq.Context()

#  Socket to talk to server
print "Connecting to hello world server…"
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")

#  Do 10 requests, waiting each time for a response
for request in range(10):
    print "Sending request %s …" % request
    socket.send("Hello")

    #  Get the reply.
    message = socket.recv()
    print "Received reply %s [ %s ]" % (request, message)

【讨论】:

【参考方案2】:

我会选择命名管道,在您的情况下很容易使用,因为它类似于读取和写入文件,但它也具有类似于套接字的功能,即您可以使它们在网络上通信(不同的主机)

【讨论】:

【参考方案3】:

Would therefore it be better to use Sockets?

在网络上工作时,您将始终使用套接字。我们可以说套接字是每个网络应用程序的核心。这么说,在回答你的问题时,我认为你的应用程序非常简单(正如你所描述的那样),所以最好不要使用一些第三方模块甚至整个框架来做到这一点。

查看此答案 Python - Sending files over sockets 这给 c c send and receive file

希望对你有所帮助。

【讨论】:

【参考方案4】:

Python 是基于 C++ 的,它是一种改进。

如果您想在一台计算机上的这些应用程序之间发送它,您可以使用文件映射。 http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx 我认为这是最好的方法。

但是,如果你想在两台计算机之间发送,一定要使用 TCP Sockets

【讨论】:

Python 是基于 C++ 的?真的吗? 可能是基于 C 的,但它就像它的实现 不,事实并非如此。主要的 Python 实现 CPython 是用 C89 编写的,但它既不存在也不存在。

以上是关于不同服务器之间的数据同步(skynet 和 c++)的主要内容,如果未能解决你的问题,请参考以下文章

skynet教程(3)--服务的别名

详解C++多线程

skynet网络层内存泄漏

Oracle不同数据库之间同步处理方案

在 C++ 中的两个线程之间同步变量的正确方法是啥?

rsync进行不同服务器之间的数据同步