Skip to content

Instantly share code, notes, and snippets.

@stableShip
Last active July 14, 2021 09:06
Show Gist options
  • Save stableShip/29884c36c93b672e1724 to your computer and use it in GitHub Desktop.
Save stableShip/29884c36c93b672e1724 to your computer and use it in GitHub Desktop.
redis 优化方案
#目的: 优化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中用户数据.
@ipengyo
Copy link

ipengyo commented Mar 20, 2018

楼主你这样做了吗?你采取是哪种方案呢。。

@stableShip
Copy link
Author

方案二

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment