目录

  • 背景
  • 合服处理
    • 防止主键冲突

      • 合服时处理冲突
      • 开服时预分配防止后续冲突
    • 字段顺序不一致

背景

滚服类型的游戏常见于 手游、网游(包括H5), 滚服类型游戏的特点(与传统大服架构区别):

  • 单服同时在线游戏人数少(eg. 3000人), 达到上限就开新服

以下这部分内容来自: https://www.cnblogs.com/youjiaxing/articles/10491357.html

滚服模式是游戏类型,技术架构和急功近利的坑钱策略等因素共同决定的,大服游戏包括绝大部分端游,以及类COC这样类型的游戏。

另外,虽然像英雄联盟,王者荣耀这样的游戏也分服架构,但是这个并不是我理解中的“滚服游戏“,首先他们虽然分服,但是每个服的人数上限也是可以高达几十万,他们并不会发生频繁的合服情况。

而滚服游戏更多是通过游戏策略设计,鼓励玩家花钱走捷径透支游戏生命周期,甚至几天即可独霸一个服务器。从而导致其他玩家望尘莫及,即使是花钱追也性价比极低,还不如进入一个新服重新开始。

这就导致了新服一开,玩家即蜂拥而至,争先恐后练级升装备,以求最快速进入排行榜前列,如果努力一番发现落后了,可能就只能坐等下一个新服。这也导致了新服人数火爆,老服慢慢变成人烟凋零的村服,甚至没人的死服。

为了能够节约服务器带宽资源,同时让少数剩余的玩家能够玩得起来,就必须要要进行频繁的合服,把若干个互不相干的服务器玩家,合并到一个服里面;这样又开启一波玩家竞争和收割。

合服处理

合服时要特别注意:

  1. 防止主键冲突
  2. 防止唯一(unique)键不冲突 (eg. 用户昵称)
  3. 清空僵尸数据/无效玩家数据(小心数据残留, 避免数据不一致)
  4. insert into 时注意字段顺序不一致问题

处理主键冲突的办法主要有2种:

  1. 合服前预处理冲突键
  2. 开服时预分配好可能的冲突键, 合服时则无需额外处理(推荐)

防止主键冲突

合服时处理冲突

如果在一开始没有设计好数据库的话, 合服时很容易遇到的普遍情况就是: 主键冲突

游戏通常有角色表, 道具表, 一般都是用数据库的自增长(AUTO_INCREMENT)特定来创建其主键, 以此保证主键的唯一,以如下表结构为例,id 只能保证在本服中唯一,A服中有个玩家id是1, B服中也有个玩家id是1, 合服前必须解决这个冲突.

-- 玩家表
CREATE TABLE `users`(`id` int(11) unsigned not null,`name` varchar(50) default null,primary key (`id`)
) Engine=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;-- 玩家道具表
CREATE TABLE `props`(`id` int(11) unsigned not null,`user_id` int(11) unsigned not null,primary key (`id`)
) Engine=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

通常做法是给 B表中的所有 users.id 字段值加上一个基数(max('A.users.id'), 同时还要修改涉及到的其他表, 比如 props.user_id 字段必须相应修改, 否则无法关联到对应玩家,因为修改了 users.id 后一般要修改相应的数十张表中的 user_id, 同时若使用了外键还得额外处理外键的删除和重做.

实际上这种处理很繁琐,因为通常需要修改主键的不只一张表,表的关系越复杂,修改一个表的主键牵涉到的相关表越多,实际操作时层层嵌套会很恶心...

开服时预分配防止后续冲突

一种更为推荐的办法是在一开始设计好主键,提前规避冲突,这样在合服操作时就可以无脑数据合并。

1.使用自增值, 服编号在前

每个服都有一个唯一的服编号, 可以利用这一点, 提前规划好每个服的 主键区域。

比如 users 表主键 id, 当存在1万个玩家时, id取值范围为 1~10000。

先定个小目标, 我们预估单个服玩家数量不会超过1一个亿, 因此用服编号乘以这个量级, 因此1服的主键id范围 100000000 ~ 199999999, 111服的是 11100000000 ~ 11199999999,

注意这已经超出 int 表示范围, 因此必须使用 bigint, 若使用 unsigned bigint可以完整表示19位数。如果你觉得可能会超出小目标, 那可以把这个量级再调大一点, 比如100个亿。

关于mysql 数字的数据类型可以看一下这边: https://www.cnblogs.com/yiwd/p/5531167.html

牺牲一点硬盘空间来规避后续合服的恶心事项,我是觉得很划算。

2.不完全使用自增值, 服编号在后

还有另外一种预分配方案, 即一开始预估服编号的范围(比如 1~9999),将服编号作为 users.id 后N位,这样可以避免玩家看到自己一大长串的uid觉得恶心。比如1服玩家原id为23的玩家, 按照这种方案, 其id就是 230001, 111服的id为23的玩家则是 230111.

这种方案就是在生成主键id时会绕一点, 但对于 MongoDB这一类的倒无所谓了.

3.使用uuid作为主键

优点: 确保全局唯一, 不仅是表唯一, 而且是库唯一,很方便不同数据库间迁移

这种方案不好的地方在于UUID的无序性, 会导致InnoDB引擎产生巨大的IO压力, 这根InnoDB主键索引与数据存储位置相关。

字段顺序不一致

游戏版本迭代更新容易导致不同数据库结构有所差异, 因此在合服时, 一个是确保数据库版本一致.

如果是简单地使用 insert into db2.table2 select * from db1.table1 时要确保字段是一致的.

如果不一致就乖乖指定字段 INSERT INTO new_db.table_name(column1, column2,...) (SELECT column1, column2,... FROM old_db.table_name);

具体有哪些字段可以通过如下语句查出:

select COLUMN_NAME FROM information_schema.COLUMNSWHERE TABLE_NAME='table' and TABLE_SCHEMA='database';

转载于:https://www.cnblogs.com/youjiaxing/p/10495803.html

[原创]游戏合服时如何避免主键冲突相关推荐

  1. mysql insert 主键冲突_insert 时防止出现主键冲突错误的方法

    最近几天,产品上线比较多,从内网测试库导出表的部分内容到线上也就比平时频繁多了,这时候可能会出现主键冲突: Error Code : 1062 Duplicate entry '1' for key ...

  2. 一个游戏大量合服代表什么_网页游戏 合服技术分享

    我们的游戏上个星期经历了第一个数据合服.简单说,就是把2个数据库合并在一个数据库,让2个服务器的玩家一起玩. 过程简直是惊心动魄,最终还是安全完成任务. 本文就分享下合服的各种技术细节. 需求说明: ...

  3. mysql数据库合并游戏合服_关于游戏合服的资料

    原网址:http://www.cnblogs.com/zc22/archive/2011/05/30/2063365.html 我们的游戏上个星期经历了第一个数据合服.简单说,就是把2个数据库合并在一 ...

  4. django使用postgresql时提示主键冲突

    在django使用postgresql数据库时,当你使用默认主键,但当你手动使用添加记录到相关数据库时(非insert操作,如使用navicate直接在表中复制粘贴记录),此时django在插入数据时 ...

  5. sqoop从hive导入数据到mysql时出现主键冲突

    今天在将一个hive数仓表导出到mysql数据库时出现进度条一直维持在95%一段时间后提示失败的情况,搞了好久才解决.使用的环境是HUE中的Oozie的workflow任何调用sqoop命令,该死的o ...

  6. mysql数据库合并游戏合服_浅谈滚服游戏如果实现一键合服

    背景 近几年的游戏行业中,出现了各种各样的滚服游戏,包括页游,手游,H5游戏等等.滚服游戏和大服游戏的区别在于同时游戏人数,大服游戏是有很多用户在一起玩,甚至几十上百万玩家.而滚服游戏则一般会设计游戏 ...

  7. mysql数据库合并游戏合服_[转载]浅谈滚服游戏如果实现一键合服

    转载自 石匠的Blog: http://www.bugclosed.com/post/12 背景 近几年的游戏行业中,出现了各种各样的滚服游戏,包括页游,手游,H5游戏等等.滚服游戏和大服游戏的区别在 ...

  8. 滚服游戏合服之数据库数据合并

    为什么要合服? 游戏运行一段时间后(2个月,3个月不等),单服留存的玩家数量很少,而且大多是小号.为了节约服务器资源,增加玩家之间的互动,就需要把两个或者多个服务器的留存玩家合并在一起. 合服主要是数 ...

  9. mysql 主从,主主,主主复制时的主键冲突解决

    原理:slave 的i/o thread ,不断的去master抓取 bin_log, 写入到本地relay_log 然后sql thread不断的更新slave的数据 把主服务器所有的数据复制给从服 ...

最新文章

  1. 宝塔如何备份网站_学习织梦网站必需会的一件事:织梦网站数据备份
  2. 牛B人才简历中的一段
  3. 【机器学习】异常检测算法(I)
  4. [Android] Android4.0、4.1在手机上制作fastboot线刷包;
  5. 三问(why?what?how?)金融领域的机器学习
  6. Cloud一分钟 |2018天猫双11结果出炉:2135亿;工信部透露:6G概念研究也在今年启动;英特尔39款至强新处理器曝光...
  7. cefsharp 加载网页慢_网站访问慢的排查方案(史上最详细)
  8. matlab mtime,matlab中的视频分析工具箱 提供matlab中的视频分析工具 - 下载 - 搜珍网...
  9. [17] 楼梯(Stairs)图形的生成算法
  10. CCNA初学者应该知道的词
  11. php ext在哪里,PHP Ext API
  12. 表单元素设置disabled后 支持点击事件
  13. java web分享ppt大纲 -- servlet包
  14. Boost 连接库的命名含义
  15. Ubuntu下WPS 快捷键、使用方法总结
  16. matlab关于图像切割的一些总结:imcrop,getrect,ndgrid,函数
  17. 小程序开发之AppID获取
  18. 微信小程序——三角形面积计算
  19. 博客专家3月原创奖励
  20. Android开发学习—指纹识别系统的原理与使用

热门文章

  1. plc通信程序 c语言,三菱PLC编程口通信C语言源代码(3)
  2. vue可缓存的单页面多标签页
  3. 2020年春季计算机网络考试,国家开放大学2020年春季学期电大考试《计算机网络》精选考试题及答案...
  4. 流程图讲解_流程图小作文练习,详细讲解+精选范文!你们的魔鬼来了(一)...
  5. 锐捷linux上网教程,校园网Ubuntu锐捷(myxrgsu)安装联网方法
  6. IDEA中控制台中文乱码问题
  7. Codeforces Global Round 14, C. Phoenix and Towers
  8. java认证框架_sa-token 一个的JavaWeb权限认证框架,强大、简单、好用
  9. Android底部日期控件,Android开发中实现IOS风格底部选择器(支持时间 日期 自定义)...
  10. linux 看rabbit版本,Linux下安装rabbitMq