我在之前的 <python使用redis 神器 ---redisco(一)>中已经简单介绍了redisco这个python的redis库的特点。
接下来这篇文章想着重分享一下如何将python内置的数据类型通过redisco存储到redis内,实现方便的存取和原子化操作,而不用去关心存储在redis里的数据会因为多进程(线程)需要添加“锁”这种繁琐的操作。
我先讲下我当时遇到的麻烦把,公司项目中的游戏服务器在一开始开发的时候都是以单进程来调试开发的,当我们在开发一些类似于副本或者战场之类功能的时候不得不在程序内生成以为所谓的“战场”或者“副本”的数据结构来存储数据,并给在参加这些战斗的玩家共享数据。那么一般在python内部会用一个class或者dict来设计这些数据结构。
当然在单进程的情况下没有问题,因为这些数据都是在内存里交互。但是当服务器架构被改造成多进程后,不同的玩家会随机的连接在服务器的各个进程上,那么他们就不能像之前很方便的共享单进程时里这些战场的数据。
一般在今天要解决多进程数据共享也不是什么很复杂的问题了,无非是用缓存,RPC调用等等。
但是这些方法都不能很方便的解决将之前用python生成的数据结构数据进行方便的存储和读取,一般会进行一次编码和解码,比如都转成json,或者二进制,效率不高而且繁琐,最恶心的关键数据比如比分,金钱,这些在不同的进行需要进行更改时要加锁,这样性能又会下降,想想就恶心。
好了,终于可以让我们的redisco出场了,长话短说,我们来看看用它来存储python数据如何方便。
python redisco
=========================
字典,类 models.Model
列表 list
字符串,数字 key,value对
上面这张表是python内数据对应到redisco内数据结构的映射
主要讲下当你在使用redisco中models.Model用来替代python内部的字典和类时的注意事项
在models.Model中当你生成了一个数据调用save方法存入redis后比如这样写的
- from redisco import models
- class Person(models.Model):
- name = models.Attribute(required=True)
- created_at = models.DateTimeField(auto_now_add=True)
- fave_colors = models.ListField(str)
- age = models.Counter()
- score = models.IntegerField()
在你的进程内生成一个数据
test = Person()
test.name = 'xiaoming'
test.save() #存进redis
如果你不销毁test变量,那么可以一直直接访问它的属性
比如
>>print test.name
>>xiaoming
>>print test.age
>>0
修改score属性
>>test.score = 1
>>test.save()#跟新redis内数据
修改age
>>test.incr('age',5)
>>print test.age
>>5
注意区别同样是数字 redisco 内 Counter 和 IntegerField 一个不需要调用save方法一个需要
==========================
那么神奇的地方仅仅只有这点????
如果此时有个b进程也在修改test这个数据
会怎么样?
我直接告诉你结果吧
如果你要正确的修改test的score
在每次修改前都需要重新获取一次test数据
而修改age则不用,你只要调用test的incr() 和decr() 就可以修改
将简单点,在a进程和b进程同事通过 Person.objects.filter(name='tset')[0] 获取了叫‘test’名字的这个人的数据
然后a,b2个进程同时使用 test.incr('age')
再print test.age你会发现增加了2 而不是增加了1
对于list类型和zset类型在之前的文章已经提过就不细说了