转自:http://blog.chinaunix.net/uid-24517549-id-5826276.html
一、常见的游戏使用数据库方式
1、mysql或mongo等关系数据库落地,redis作为缓存、排行榜、消息队列使用
好处:
架构比较传统,程序员接受度较高。Mysql等数据库较成熟,组件丰富,数据库运维方便。
缺点:
进程扩容、更新、down机重启需要去冷数据库中重新拉取数据,或者做数据转移,容易产生性能瓶颈。
如果对数据做缓存则会有多份数据同时存在,容易导致数据不一致问题。还有缓存穿透现象。
特别是全区全服游戏,数据库压力较大。
2、共享内存缓存数据,再加上1中的数据存储方式
利用共享内存缓存数据,进程更新、重启直接从共享内存中加载数据。
好处:
只要不重启丢失,热数据一致存在内存中,带来极致的性能。比较适合腾讯这种大流量厂商。
缺点:
数据存储多份、需要自己写扩容逻辑、数据路由也比较麻烦。
3、数据存储完全使用redis
好处:
性能高,不需要关心扩缩容,数据路由问题。
合理使用,数据库这方面完全可以抗住大平台导流量的压力。
解放程序员心智,可以花更多精力在玩法、场景等游戏核心体验上。
缺点:
全内存存储,成本较高。
全redis方案在互联网行业不流行,程序员接受度较低,或者直接没考虑过这种用法。
无法自定义数据结构。
二、Redis能为游戏带来哪些好处
游戏中的玩家数据其读写都是有明显的约束的---玩家ID。Redis这种数据库和游戏可以说是天作之和,非常适合用来存储游戏数据。
1、高性能、高可靠性
单redis实例每秒可以达到10万+QPS,近似本地内存的性能。
据了解还没有因为redis本身的bug造成过游戏down机,或者redis自身down机情况。
2、数据结构、接口丰富、不需要提前配置数据结构
Zlist:排行榜
Hash:
Set:
...
除了需要强关系查询的功能,基本都可以找到实现方案。
最后还有万金油lua,涉及到事务,自定义操作都可以通过lua实现。
3、托管绝大部分数据,取代掉游戏中大部分的状态数据
基于redis的高性能与丰富的数据结构,可以将游戏绝大部分数据放入redis中;
进程中只缓存变化特频繁丢失对系统无影响的数据(如对战中的玩家位置,某次战斗中的HP等);
系统可以做到随时重启、更新、扩容。方便运维、减少各种原因导致的停机对游戏体验的的影响。
例子:
某休闲游戏的猎魔模式(玩家实时上传自身位置、在特定地点、时间点一起刷怪打怪),相当于一个简单的MMO系统。
除了房间里面的战斗数据,都是实时存入redis,进程中不缓存数据,做到了不停机、实时更新系统。扩容、单进程down机对玩家无感知。
单台物理机,32个redis实例,最高支持20万玩家同时在线。
三、Redis目前存在的问题
1、官方集群方案对客户端不透明
官方集群方案对客户端不透明。(尽管官方6.0 出了个 mysql-cluster-proxy,但试了一下,垃圾的一批;主库挂了自动故障转移,并无法识别出来)
开源的代理不适合游戏:
(1)codis本身性能较低,容易造成单点。
(2)Twemproxy除了上面的问题外也不支持在线扩容,没人维护(例如新加入的geo命令就不支持)。
听说现在都是用对应的开源框架去连接 redis-cluster的,比如 jedis,我倒是没有用过;
2、落地方式比较粗糙
Rdb全量落地、利用系统cow特性,fork子进程进行落地。需要两倍的内存容量。
AOF实时落地
3、数据无法回滚到任意时间点
Rdb落地间隔较长,aof格式中没有时间戳。回滚只能回滚到大概的时间节点,不能保证强一致性。
4、数据全存内存中
成本较高,机器有问题则数据丢失,利用rdb与aof加载数据需要时间较长。
5、单线程
单线程避免了线程切换和竞态产生的消耗。但是对于每个命令的执行时间有要求。如果某个命令执行时间过长会造成其它命令的阻塞。
这在 redis6.0.4 后已经可以支持多线程,官方建议4个线程,最多支持8个线程
四、我们需要的Redis:自动化运维、平滑扩容、高可用
1、自动申请、部署redis系统
2、通过代理实现集群功能、代理和后端的redis都可以平滑扩容
3、代理屏蔽后端redis实例的主从切换
4、日志功能的二次开发,必要的情况下可以回滚到任意时间点
五、全面的监控预警系统
1、zset,list元素个数,热key,大key,慢查询
有的时候开发会将大量数据存储在一个key中,造成key的数据量太大,容易造成系统阻塞。
通过监控热key可以找出系统单点瓶颈。比如一个全区排行榜操作太频繁造成系统卡顿。可以实时告警,为开发优化系统提供建议。
大key和慢查询是各种数据中基本的监控项。
六、冷热自动分离
1、冷数据淘汰出内存,存入硬盘
2、自动备份、扩容
3、方便好用的日志,数据导出等周边工具