Last active
July 14, 2021 09:06
-
-
Save stableShip/29884c36c93b672e1724 to your computer and use it in GitHub Desktop.
redis 优化方案
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#目的: 优化leancloud的api使用次数,使用redis进行缓存 | |
# 优化方案一: | |
对整个系统进行redis缓存,所有的数据操作都是直接操作redis数据 | |
优点:redis数据可视 | |
缺点:对当前代码改动太大(所有基础类操作都改成对redis的操作),数据管理难度较大,优化时间长 | |
难点:对象数组的组织,数据序列化 | |
举例: 如果说吧成就系统数据保存为 hash结构: | |
``` | |
[{"billionaire:avhievement:oucnUjntO-xdbdaWOkRME_YN0IXc": | |
{ | |
"id": 1, | |
"achievement_id": 1, | |
"status": 0, | |
"progress": 0 | |
} | |
}] | |
``` | |
该数组保存到redis中,必须拆分成多个key,如: | |
"billionaire:玩家唯一标识:achievement:成就id":{ | |
"id": 1, | |
"achievement_id": 1, | |
"status": 0, | |
"progress": 0 | |
} | |
写一个方法,是从redis中读取数据的方法,将redis中的各个模块的key读取出来,组合成对象的方法.该对象有基础的修改方法,例如:save方法,调用的时候,将用户数据,按照不同的模块,保存到redis中,get方法:调用redis中的hget获取相应数据,set方法,调用redis中的hset保存数据. | |
例如:总的player对象中,有一个achievements的数组对象,当我们从数据库中读取数据的时候(假设还没有保存在redis中),保存到redis中(要写一个将leancloud对象保存到redis中的方法),然后再从redis中读取数据,然后 | |
``` | |
for achievement in player.achievements: | |
achievement.status = 2 | |
achievement.save() # 调用redis中的hmset把所有achievement的数据保存到redis中 | |
``` | |
## 第二步 添加新的achievement | |
如果使用了上面的结构,如何添加一个新的achievement,,在player中定义一个add_achievement的方法,调用redis的hmset,根据不同的用户,成就,进行相应的保存 | |
# 第二种方案: 简单粗暴法 | |
从数据库中读取出数据后,json.dumps保存到redis中,然后从redis中取出来,重新变成python的基础类(和现在leancloud的基础类一些方法不一样,可以尝试在Base_Entity中将leancloud的方法模拟,那么所有的api就不需要改变了) ,然后,每一次用户请求的时候,就从redis中读取数据,转换成Python基础类,然后请求结束,就将类json.dumps保存到redis中. | |
优点: 项目现有结构不需要改变,所有基础类都不需要改变 | |
缺点:无法使用redis的原子操作,可视化. | |
``` | |
def save_to_redis(self): | |
""" | |
保存用户数据到redis中 | |
:return: | |
""" | |
redis_cli = redisTool.get_conn() | |
data = pickle.dumps(self) | |
key = Redis_Prefix.Player + self.openid | |
return redis_cli.set(key, data) | |
``` | |
``` | |
def save_to_db(self): | |
print "保存玩家:%s 到数据库" % self.openid | |
for attribute in self.attributes: | |
att = getattr(self, attribute, None) | |
if att: | |
is_list = att.__class__ == [].__class__ | |
is_set = att.__class__ == set().__class__ | |
if is_list or is_set: | |
for obj in att: | |
if obj: | |
obj.save() | |
elif not isinstance(att, unicode): | |
att.save() | |
self.save() | |
``` | |
## 共同点 数据落地 | |
1G内存redis,大概能够保存5万玩家数据 | |
1024*1024/20 = 52428 | |
### 用户重要数据改变时,进行落地,怎么落地: | |
将redis中的数据全部取出来的,然后一个一个的调用leancloud的save方法,保存到leancloud. | |
对于新增的数据的处理会是一个难点 | |
使用了redis的sortedset记录用户操作时间戳,通过一个定时器,每五分钟查找一次最小值(也就是最久没有操作的),通过判断该值是否超过15分钟,是的话将用户数据取出,保存到数据库,然后删除sortedset中的记录,删除redis中用户数据. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
楼主你这样做了吗?你采取是哪种方案呢。。