使用DCS实现游戏开合服的数据同步
方案概述
应用场景
游戏业务开合服,指一些大型网络游戏为了吸引新玩家,在运营一段时间后,会开启新服务区,当新服务区开放后,老服务区用户存在流向新服务区的趋势,用户数逐渐减少,为了改善老服务区用户的游戏体验,延长游戏生命周期,游戏开发商通常会进行新老服务区合并,将新开和原有的两个服务器(区)的数据合并到一个服务器(区),使新老玩家就能在同一个区进行游戏。在这个过程中,会遇到如何将不同服务器数据同步的相关问题。
解决方案
在游戏开合服方面,使用分布式缓存服务(DCS)的Redis缓存可以应用到以下场景:
- 跨服数据同步
游戏合服后,需要将多个游戏服务器的数据进行同步,以保证游戏数据的一致性。可以使用Redis的消息队列pub/sub机制,将数据变更消息发布到Redis的频道中,其他游戏服务器订阅该频道,接收数据变更消息,从而实现数据同步。
- 跨服资源共享
游戏合服后,可以将多个游戏服务器的资源进行共享,例如玩家道具、金币等。可以使用Redis的分布式锁机制,来保证多个游戏服务器对资源的访问互斥,避免资源冲突。
- 跨服排行榜
游戏合服后,可以将多个游戏服务器的排行榜进行合并,以展示全服的排名情况。可以使用Redis的有序集合机制,来存储排行榜数据,并进行排名计算和查询。
在以上三种应用场景中,“跨服资源共享”的实现方式可以参考使用DCS实现热点资源顺序访问,“跨服排行榜”的实现方式可以参考使用DCS实现排行榜功能。
本篇文档主要介绍如何通过Redis的消息队列pub/sub机制,实现“跨服数据同步”。
在使用Redis进行游戏合服方面的应用时,需要考虑数据一致性、性能和安全等方面的问题,避免出现数据错误、性能瓶颈或者安全漏洞等问题。
前提条件
- 已创建DCS缓存实例,且状态为“运行中”。
- 客户端所在服务器与DCS缓存实例网络互通:
- 客户端与Redis实例所在VPC为同一VPC
- 客户端与Redis实例所在VPC为相同region下的不同VPC
如果客户端与Redis实例不在相同VPC中,可以通过建立VPC对等连接方式连通网络,具体请参考:缓存实例是否支持跨VPC访问?。
- 客户端与Redis实例所在VPC不在相同region
如果客户端服务器和Redis实例不在同一region,仅支持通过云专线打通网络,请参考云专线。
- 公网访问
客户端公网访问Redis 4.0/5.0/6.0实例请参考使用Nginx实现公网访问DCS或使用华为云ELB公网访问DCS。
实施步骤
- 使用Redis-py库中的Redis()方法在每个游戏服务器上创建一个Redis客户端连接。
- 使用pubsub()方法在每个游戏服务器上创建一个Redis订阅者和发布者。用于订阅其他游戏服务器发布的消息,以及发布本地游戏服务器的数据更新消息。当某个游戏服务器需要更新数据时,它会将更新的消息发布到Redis消息队列中。其他游戏服务器会收到更新消息并相应地更新各自的本地数据。
- 定义一个publish_update()方法发布更新消息,并在listen_updates()方法中使用subscriber.listen()方法来监听更新消息。
- 当收到更新消息时,通过调用handle_update()方法来处理更新消息并更新本地数据。在游戏服务器中,通过调用publish_update()来发布更新消息,以及调用listen_updates()来监听更新消息。
示例代码
以下是使用Redis-py库实现消息队列pub/sub机制进行游戏跨服数据同步的示例代码(本示例代码以python2为例):
import redis # 创建Redis客户端连接,Redis实例连接地址和端口需替换为实际获取的值 redis_client = redis.Redis(host='localhost', port=6379, db=0) # 创建Redis订阅者 subscriber = redis_client.pubsub() subscriber.subscribe('game_updates') # 创建Redis发布者 publisher = redis_client # 发布更新消息 def publish_update(update): publisher.publish('game_updates', update) # 处理更新消息 def handle_update(update): # 处理更新消息,更新本地数据 print('Received update:', update) # 监听更新消息 def listen_updates(): for message in subscriber.listen(): if message['type'] == 'message': update = message['data'] handle_update(update) # 在游戏服务器中调用发布更新消息的方法 publish_update('player_data_updated') # 在游戏服务器中调用监听更新消息的方法 listen_updates()
输出结果:
D:\workspace\pythonProject\venv\Scripts\python.exe D:\workspace\pythonProject\test2.py Received update: b'player_data_updated'