目录
(1)该数据属于短暂保留,例如只保留三天、七天或者一个月,此时建议采用缓存;
(2)该数据在某一个时间段请求量很大,此时建议采用缓存;
(3)随着用户使用,数据不断变化,更新操作比较频繁,此时建议采用缓存;
(4)如果数据量不大,且和应用性能提升不大,数据需要长久保留,此时不建议采用Redis进行缓存,直接使用MySQL等关系型数据库存储即可;
(5)如果数据量很大,但是过了一段时间后,该数据几乎没有什么价值,此时建议采用缓存,并设定过期时间和定时清理该数据的脚本,这样处理可以减轻存储空间,也便于优化系统的数据库层。
(1)缓存该key在极端情况下,占用系统内存会有多大?或者说存储的记录大概会达到什么数量级?
(2)缓存该key,过期时间是否方便设置?如果不方便设置,是否可以隔段时间考虑转存到MySQL等关系型数据库中,从而清理缓存,释放内存空间。
(3)缓存该key,思考一下手动删除缓存数据的脚本如何编写,缓存的所有数据,如何区分出有价值的数据进行保留,无价值的便利用脚本进行自动化删除。
(4)使用缓存后,要思考选择恰当的数据结构来完成代码构建。因为一个适合的数据结构不仅使得代码变得更加优雅,后期维护也很方便。
如果发现某一个key占用内存很大,超出预料,提供的优化建议:
(1)分析该key的具体实际功能,和目前的需求,看能否在后续缓存数据时,添加过期时间设定;
(2)考虑在取出缓存数据的时候,能否转存到MySQL等关系型数据库,如果能够转存成功,则在此处可以进行立即执行删除该条缓存数据的方法;后续取数据时,可采用先查询Redis数据库,未查到再次查询一下MySQL等关系型数据库;
(3)依据已经缓存的数据,看能够依据数据中的字段或者相关属性对已经缓存的数据进行过滤查询,把那些不重要的数据通过脚本进行手动删除处理。
例如,定义了以下两个客户端:
# -*- coding: utf-8 -*-" from django.conf import settings import redis redis_db_client = redis.StrictRedis( host=settings.REDIS[‘redis_db_host‘], port=settings.REDIS[‘redis_db_port‘], db=settings.REDIS[‘redis_db_db‘], socket_connect_timeout=4, socket_timeout=2, decode_responses=True, ) redis_hot_client = redis.StrictRedis( host=settings.REDIS[‘redis_hot_host‘], port=settings.REDIS[‘redis_hot_port‘], db=settings.REDIS[‘redis_hot_db‘], socket_connect_timeout=2, socket_timeout=2, decode_responses=False, )
此时,可以依据key的设计和作用,选择合适的客户端来操作。其中不同的客户端对应的端口和具体数据库不同,以上客户端定义仅作参考。(PS:以上定义是基于Django框架的配置文件来使用,其它Python框架也可以类似定义)
在定义redis操作key的名称建议采用大写字母加下划线组成;在初始化key对象时,最好能够设定过期时间。
Key定义的类示例:
class RedisKey: """RedisKey类对象""" def __init__(self, prefix, ex=None): self.prefix = prefix self.ex = ex # 生成key值 def __call__(self, key): return self.prefix + str(key)
则定义一个key的示例:
USER_PULL_URL = RedisKey(prefix=‘user_pull_url:‘, ex=8 * 60 * 60)
其中参数prefix为key存储在Redis数据中具体的键名,可以通过调用__call___方法来为key添加后缀,例如user_pull_url:1808表示一个键名;ex为该key对象定义的过期时间设定,等到具体编写该key的添加操作时,调用参数ex来设定key的具体过期时间。
其中key存放的文件,要依据选择的客户端存放在指定的文件中,这样方便查看和管理。
Redis数据库包含String(字符串)、Hash(哈希表)、List(列表)、Set(集合)、SortedSet(有序集合)五种数据结构。下面简单介绍一下这五种数据结构的特性:
每一个服务层,建议单独创建一个cache.py文件,专门用于存放操作Redis数据库层的方法,此类的功能可以类比models.py文件。
每一个key使用其键名创建符合代码规范的类名,然后在该key对应的类里面,定义操作的redis_client和redis_key,最后通过cliet和key定义相关数据的添加、修改、查询和删除的方法。
最后,最重要的一点建议:该cache.py中定义的操作方法建议只在该服务层中被其它类中方法体调用。这样的好处,可以让我们对于该key在以后的数据管理上有可控的预估操作,也使得代码调用变得更加规范。
此处给出一个示例:
定义一个key:
键名初始化:
USER_SESSION = RedisKey(prefix=‘user_session:‘, ex=4 * 60 * 60)
选择客户端:
redis_hot_client
在cache.py中定义的类和相关操作方法:
class CacheUserSession: # 类名和key的名称对应 """ 原始数据类型: dict 存储数据类型: bytes 数据说明:将user_dict序列化成二进制数据,存入Redis中 """ db = redis_hot_client key_prefix = rediskey.USER_SESSION @classmethod def get(cls, user_id: IdInt): key = cls.key_prefix(user_id) # key的具体初始化值 user_dict = cls.db.get(key) if user_dict: user_dict = pickle.loads(user_dict) return user_dict @classmethod def delete(cls, user_id: IdInt): # key的删除方法定义 key = cls.key_prefix(user_id) cls.db.delete(key) logger.info("Delete UserSession:{}".format(user_id)) @classmethod def set(cls, user_id: IdInt, user_dict: dict): key = cls.key_prefix(user_id) data = pickle.dumps(user_dict) cls.db.set(key, data, ex=cls.key_prefix.ex) # 注意设定过期时间 logger.info("Set UserSession:{}, {}".format(user_id, user_dict))
此处,给出一个很好用的存储数据的途径。通过以下途径,可以把一个字典格式的数据当作字符串存入Redis数据库,取出后可以重新解析出字典格式。通过该途径,可以较好的把Redis当作关系型数据库存储一样,一条数据记录可以存储多个属性的值。
例如,一个学生,包含学号、姓名、性别、年级、专业等属性。如果采用关系型数据库存,以学号作为主键,其它属性作为列名进行设计,通过学号即可查询出该学生的所有信息。但是,一个学生的多个属性信息如何存储到Redis数据库中,并且取出来能够很好的使用呢?
采用的策略:学号唯一,可作为key值,姓名、性别、年级、专业联合成一个字典,在存入Redis数据中之前先转换为指定结构的字符串格式,取出后再解析成字典格式。这样操作就能很好的解决这个需求。
为什么要转换为字符串格式存入Redis数据库呢?因为不管什么数据结构的数据存入到Redis数据库中后,它取出都是字符串格式。
下面请看具体代码示例(具体cache.py中CacheStudent类实现代码不给出噢):
import json
value_data = json.dumps({ name: "xiaoming", gender: "male", grade: "2014", profession: "软件工程", }) # 通过json模块把字典转换为指定格式的字符串 CacheStudent.set(student_id, value_data) # 通过定义好的写入方法,把指定的学生数据存入 student_data = json.loads(CacheStudent.get(student_id)) # 取出指定学号学生的数据后,使用json模块的loads方法解析该字符串变成字典格式 print(studnet_data["name"]) # 打印该学生的姓名信息 print(studnet_data["gender"]) print(studnet_data["grade"]) print(studnet_data["profession"])
看到上述的实现,是不是发现Redis存储可以当作关系型数据存储来用?
此处调用,可适当选择时机何时进行数据删除操作。比如取出后,可以选择把最终存储的数据转存到MySQL数据库中,然后调用cache.py中的删除方法,对该数据记录进行删除操作。
原文:https://www.cnblogs.com/liuzhen1995/p/9374786.html