文章目录
- 一、热更新方案选择
- 1)重载lua(C++/lua)
- 2)C++重新加载动态库(函数重载)
- 3)增加一组逻辑服务器
- 二、纠结点
- 1)数据应该如何缓存?
- 2)缓存服务器是自己写还是采用现有的关系数据库?
- 3)以上方案哪种比较靠谱?
- 三、对应方案选择回答
- 1)回答一
- 2)Linux 动态加载并调用动态库(.so)方法介绍
- (1)概念
- (2)头文件
- (3)相关函数介绍
一、热更新方案选择
1)重载lua(C++/lua)
使用C++/Lua.用Lua写逻辑.这样如果只是逻辑改变的话就只用引擎重新加载Lua虚拟机即可
(shell脚本输入 reload -s 服务器读取指令重载lua虚拟机)
2)C++重新加载动态库(函数重载)
使用C++加载动态库写逻辑.逻辑更新的话则重新加载动态库即可.使用主框架来缓存数据
3)增加一组逻辑服务器
- 目的
每次维护只更换逻辑服务器.而且玩家连接到任何一组逻辑服务器都不影响操作的目的. - 涉及到读到内存的数据
当txt的策划配表数据读到内存中时,要改变这部分的数据,就用引用计数的方法,当没有代码用到这部分的数据,引用数为0时,替换这部分数据
二、纠结点
1)数据应该如何缓存?
对于复杂的业务操作可能需要大量的缓存数据以支持判断查找修改(比如大规模混战/国战)等等.那在这种情形下.如何才能确保能最快捷地从缓存中取到大量数据.
2)缓存服务器是自己写还是采用现有的关系数据库?
NoSQL.比如Redis,memcached之类.如果用这样现成的NoSQL,如何保存一些比较复杂的结构数据.
3)以上方案哪种比较靠谱?
三、对应方案选择回答
1)回答一
- 对于C++重新加载动态库的问题
最好不要用动态库的形式转移数据,不能跨平台
是一定的,并且跨动态库维护数据很容易出问题,特别是涉及全局变量和静态变量的时候。单例模式的实现基本都是全局变量或者静态变量 - 外部缓存服务比较靠谱
外部缓存服务是比较靠谱的,你自己能写当然最好,没时间写完整的话用redis什么的也行啊。具体哪些用现成的哪些自己写还是要根据具体项目需要的。我们就是一部分用redis,一部分自己写。但是一定要控制好淘汰机制。 - tsf4g(tbus)
其实这货并没有规定你一定要用共享内存放数据。而且如果你实在想用共享内存放数据的话,很多都要手动处理。所有对象得自己维护索引,然后在进程重启后恢复索引。然后基本上你就和stl容器告别了,因为所有数据里都不能存任何地裸指针,当然你可以用boost的方法存偏移指针,或者按类型写支持共享内存和stl容器的allocator。很多用tsf4g的项目是用index的。如果你想用任何堆相关的算法,红黑树,链表等等,自己写。
(共享内存放数据还有一个比较麻烦的是,如果对象内存布局变化了,你必须能够检测到并且正确升级,这点很重要。所以我的建议是,除非你要写大型MMO游戏,否则用共享内存绝对性价比太低呀。) - 目前的做法
更新服务器的时候部署另一组,然后部署完后把路由切过去,最后通知所有老服务器的玩家断线重连。就完事儿了,部署的时候慢就慢一点呗。不过我们对不同类型的缓存有优化,会控制到它并不太大就是了。
2)Linux 动态加载并调用动态库(.so)方法介绍
(1)概念
加载动态链接库,首先为共享库分配物理内存,然后在进程对应的页表项中建立虚拟页和物理页面之间的映射。你可以认为系统中存在一种引用计数机制, 每当一个进程加载了共享库(在该进程的页表中进行一次映射),引用计数加一;一个进程显式卸载(通过dlclose等)共享库或进程退出时,引用计数减 一,当减少到0时,系统卸载共享库。
(2)头文件
#include <dlfcn.h>
(3)相关函数介绍
(1)打开动态链接库:dlopen
函数原型
void *dlopen (const char *filename, int flag);
flag:分为这两种
RTLD_NOW:在dlopen返回前,解析出全部没有定义的符号,解析不出来返回NULL。
RT_GLOBAL:动态库定义的符号可被其后打开的其他库解析。
RT_LOCAL:和上面相反,不能被其他库解析。默认。
RTLD_LAZY:暂缓决定,等有需要时再解出符号
返回值:
打开错误返回NULL
成功,返回库引用
dlopen用于打开指定名字(filename)的动态链接库(最好文件绝对路径),并返回操作句柄。
(2)取函数执行地址:dlsym
函数原型
void *dlsym(void *handle, char *symbol);
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。
(3)关闭动态链接库:dlclose
函数原型
int dlclose (void *handle);
returns 0 on success, and nonzero on error.
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
(4)动态库错误函数:dlerror
函数原型
const char *dlerror(void);
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
(5)代码示例
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/tmp/libtest.so", RTLD_LAZY);
if (!handle) {
fprintf (stderr, "%s ", dlerror());
exit(1);
}
cosine = (double(*)(double))dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s ", error);
exit(1);
}
printf ("%f ", (*cosine)(2.0));
dlclose(handle);
return 0;
}