我正在用Python/Django开发一款回合制策略浏览器游戏。其理念是:玩家在第n回合与网站互动。他们观察自己的游戏状态(游戏邦注:即游戏"世界"),并发布将在下一个时间步骤评估中执行的命令。在某个时间点,网站被冻结,回合引擎从时间步n的状态加上所有玩家的订单列表中计算出时间步n+1的新游戏状态。在这个时间步求值期间,我需要从时间步n读取对象的状态,并在时间步n+1创建/写入对象。如何以最有效的方式实现这一点?(这是一个关于数据库设计的问题)
我考虑了以下选项:第一种方法是:让每个世界对象携带一个时间步长参数。总是按时间步长过滤可能会很麻烦。此外,数据库将随着时间步长而增长,因为它将包含自时间步长0以来的整个历史。
第二种方法是:对每个时间步骤使用不同的物理上不相交的数据库。也就是说,在时间步演变过程中,为时间步n+1创建一个新的数据库。在求值期间,同时处理数据库(n, n+1)。一旦时间步求值完成,删除(或者更好:存档)时间步n的数据库,并用数据库n+1替换它。(这样做的好处是,每个时间步骤都有一个数据库快照作为备份)对我来说,后者似乎是更好的方法。但是我需要一些关于如何同时处理两个数据库的建议。
你能给我其他的建议来做选择吗?你觉得还有其他可行的方法吗?有任何第三方库或Django插件处理类似的问题吗?如果我使用第二种方法,我怎么能告诉Django同时使用两个数据库,每个数据库中都有相同类型的对象?
我想你已经基本明白了。两个数据库,default
和future
。
DATABASES = {
'default': {
'NAME': 'default',
'ENGINE': 'django.db.backends.mysql',
'USER': '',
'PASSWORD': '',
},
'future': {
'NAME': 'future',
'ENGINE': 'django.db.backends.mysql',
'USER': '',
'PASSWORD': '',
},
}
写你的视图/任何正常使用模型像往常一样。这些将被写入default
数据库,因为你可能已经习惯了。
创建一个更新游戏状态的管理命令…(您也可以将此代码扔到芹菜任务或其他东西中,但对于这个答案,我计划使用cron调度器通过命令行调用。)
# project/app/management/commands/run_turn.py
from django.conf import settings
from django.core.management.base import BaseCommand
import subprocess
from optparse import make_option
def copy_default_to_future():
# Copy database before acting on game state
# use the subprocess library for bash execution of mysql/postgres commands
# ...
def copy_future_to_default():
# Copy database after acting on game state
# use the subprocess library for bash execution of mysql/postgres commands
# ...
def upload_backup_to_cloud():
# i recommend using django-cumulus and a custom backups storage container
# ...
class Command(BaseCommand):
args = '<attachment_path attachment_path ...>'
help = 'Processes game state at end of turn'
option_list = BaseCommand.option_list + (
make_option('-u', '--upload-backup',
action='store_true',
dest='upload',
default=False,
help='Upload database export to cloud object storage'),
)
def handle(self, *args, **options):
if options.get('upload', None):
upload_backup_to_cloud()
copy_default_to_future()
# ... change your gamestate
for player in Player.objects.using('future').all():
player.increment()
# ...
copy_future_to_default()
print "Game state updated."
patrick@lucca:~$ crontab -e
@hourly /home/patrick/.virtualenvs/browsergame/bin/python /path/to/project/manage.py run_turn --upload-backup
引用:
- https://docs.djangoproject.com/en/dev/topics/db/multi-db/selecting-a-database-for-save