基于Python使用Redis的一些想法和建议
目录
1关于Redis使用的一点想法
1.1进行缓存前,需考虑
(1)该数据属于短暂保留,例如只保留三天、七天或者一个月,此时建议采用缓存;
(2)该数据在某一个时间段请求量很大,此时建议采用缓存;
(3)随着用户使用,数据不断变化,更新操作比较频繁,此时建议采用缓存;
(4)如果数据量不大,且和应用性能提升不大,数据需要长久保留,此时不建议采用Redis进行缓存,直接使用MySQL等关系型数据库存储即可;
(5)如果数据量很大,但是过了一段时间后,该数据几乎没有什么价值,此时建议采用缓存,并设定过期时间和定时清理该数据的脚本,这样处理可以减轻存储空间,也便于优化系统的数据库层。
1.2进行缓存后,需考虑
(1)缓存该key在极端情况下,占用系统内存会有多大?或者说存储的记录大概会达到什么数量级?
(2)缓存该key,过期时间是否方便设置?如果不方便设置,是否可以隔段时间考虑转存到MySQL等关系型数据库中,从而清理缓存,释放内存空间。
(3)缓存该key,思考一下手动删除缓存数据的脚本如何编写,缓存的所有数据,如何区分出有价值的数据进行保留,无价值的便利用脚本进行自动化删除。
(4)使用缓存后,要思考选择恰当的数据结构来完成代码构建。因为一个适合的数据结构不仅使得代码变得更加优雅,后期维护也很方便。
1.3缓存使用一段时间后
如果发现某一个key占用内存很大,超出预料,提供的优化建议:
(1)分析该key的具体实际功能,和目前的需求,看能否在后续缓存数据时,添加过期时间设定;
(2)考虑在取出缓存数据的时候,能否转存到MySQL等关系型数据库,如果能够转存成功,则在此处可以进行立即执行删除该条缓存数据的方法;后续取数据时,可采用先查询Redis数据库,未查到再次查询一下MySQL等关系型数据库;
(3)依据已经缓存的数据,看能够依据数据中的字段或者相关属性对已经缓存的数据进行过滤查询,把那些不重要的数据通过脚本进行手动删除处理。
2编写Redis数据库层规范建议
2.1选择适合的redis客户端
例如,定义了以下两个客户端:
# -*- 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框架也可以类似定义)
2.2规范化定义key的名称并初始化
在定义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存放的文件,要依据选择的客户端存放在指定的文件中,这样方便查看和管理。
2.3 选择合适的数据结构
Redis数据库包含String(字符串)、Hash(哈希表)、List(列表)、Set(集合)、SortedSet(有序集合)五种数据结构。下面简单介绍一下这五种数据结构的特性:
- String(字符串):添加数据时,采用key-value格式进行存储。key是定义的键名,在上面(2)中已有说明。value是具体要存储的数据,该数据的类型是String类型。遇到的需求中,例如需要存储某用户的在线时长,可以采用key_user_id组成键名,具体时长存储在value中,此时可选择String数据结构来存储,比较方便。
- Hash(哈希表):添加数据时,采用key-value格式来进行存储,不过这里的value表示一张哈希表。可以这样做比喻,key比作关系型数据库中的表名,value存储该关系型表中的所有行的数据记录。
- List(列表):添加数据时,采用key-value格式来进行存储,不过这里的value表示一个具体的列表。该列表的功能可类似C++数据结构列表一样,有出表操作,计算列表长度操作,依据下标获取某个元素的功能,获取指定区间内的列表元素,从列表头部插入元素或者尾部插入元素等。
- Set(集合):添加数据时,采用key-value格式来进行存储,这里的value存储和Hash(哈希表)存储类型,而Set(集合)区别在于在添加数据记录时,会自动过滤掉相同值得记录,如果插入多条记录相同得数据,在Set(集合)存储得value中只会找到一条记录。
- SortedSet(有序集合):添加数据时,采用key-value格式来进行存储。存储的方式实现功能和Set(集合)基本相同,但是其唯一突出的特点就是在存数据的时候要存储元素值对应的score值,也就是依据score值的大小来对value中元素进行排序存储。后续有查询操作时,可以很方便的返回value中元素的排序序列。
2.4 规范化定义操作方法
每一个服务层,建议单独创建一个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存储可以当作关系型数据存储来用?
2.5 开始愉快的调用之旅
此处调用,可适当选择时机何时进行数据删除操作。比如取出后,可以选择把最终存储的数据转存到MySQL数据库中,然后调用cache.py中的删除方法,对该数据记录进行删除操作。
基于Python使用Redis的一些想法和建议的更多相关文章
- Python 基于python操纵redis入门介绍
基于python操纵redis入门介绍 by:授客 QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3.3.2 基于Python操作R ...
- 基于Python操作redis介绍
(注:本文部分内容摘自互联网,由于作者水平有限,不足之处,还望留言指正.) 毕业前的最后一个学期(2016.03),龙哥结婚了.可是总有些人喜欢嘲笑别人,调侃我.当时我就理直气壮的告诉他们,等龙哥孩子 ...
- 基于Python,scrapy,redis的分布式爬虫实现框架
原文 http://www.xgezhang.com/python_scrapy_redis_crawler.html 爬虫技术,无论是在学术领域,还是在工程领域,都扮演者非常重要的角色.相比于其他 ...
- Python 基于python+mysql浅谈redis缓存设计与数据库关联数据处理
基于python+mysql浅谈redis缓存设计与数据库关联数据处理 by:授客 QQ:1033553122 测试环境 redis-3.0.7 CentOS 6.5-x86_64 python 3 ...
- 基于Twemproxy的Redis集群搭建以及想法
基于Twemproxy的Redis集群方案(转) redis3.0 已经发布了几个月了,但是我这等菜鸟到网上还是没有找到很好的关于搭建redis3.0集群的文章,而且好像很多公司的redis版本还保持 ...
- 基于Python项目的Redis缓存消耗内存数据简单分析(附详细操作步骤)
目录 1 准备工作 2 具体实施 1 准备工作 什么是Redis? Redis:一个高性能的key-value数据库.支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使 ...
- Python分布式爬虫打造搜索引擎完整版-基于Scrapy、Redis、elasticsearch和django打造一个完整的搜索引擎网站
Python分布式爬虫打造搜索引擎 基于Scrapy.Redis.elasticsearch和django打造一个完整的搜索引擎网站 https://github.com/mtianyan/Artic ...
- 基于Python+Django的Kubernetes集群管理平台
➠更多技术干货请戳:听云博客 时至今日,接触kubernetes也有一段时间了,而我们的大部分业务也已经稳定地运行在不同规模的kubernetes集群上,不得不说,无论是从应用部署.迭代,还是从资源调 ...
- python之redis和memcache操作
Redis 教程 Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理.Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据 ...
随机推荐
- Linux学习笔记:scp远程拷贝文件
scp是secure copy的简写,用于Linux下进行远程拷贝文件的命令,类似的有cp,不过cp仅在本机上进行拷贝不能跨服务器. 命令格式: scp [参数] [原路径] [目标路径] -q 不显 ...
- linux下如何使用gdb调试
gdb是linux下非常好用的一个调试工具,虽然它是命令行模式的调试工具,但是它的功能强大到你无法想象,这里简单介绍下gdb下常用的命令. 首先编译生成可执行文件(这里的test.c是一个简单的求前n ...
- DDD领域模型实现依赖注入(六)
添加下订单的值对象: public partial class CustomerInfo:ValueObject { /// <summary> /// 下订单的值对象 /// </ ...
- 把A表的多个字段更新到B表
sqlServer中可用 update A set A.sex = B.sex, A.na=B.na from A,B where A.id = B.id mysql没试,应该也可以 Mysql版本 ...
- Jenkins Pipline语法
引用自:http://baijiahao.baidu.com/s?id=1582812185263227836&wfr=spider&for=pc 引用自:https://www.cn ...
- poj 1797 最大最小路段【dijkstra】 (经典)
<题目链接> 题目大意: Hugo Heavy要从城市1到城市N运送货物,有M条道路,每条道路都有它的最大载重量,问从城市1到城市N运送最多的重量是多少. 解题分析: 感觉这道题用dijk ...
- iOS 技术篇:__VA_ARGS__实现自定义NSLog
系统的NSLog 我个人觉得有bug时,没准确的说明哪一行出现的问题,所以为了方便自己开发查找问题,附上自己的NSLog 创建定义方式: 1:在创建好的pch文件里 配置: 2:在pch文件里添加上这 ...
- 在网站中使用Bing Translator插件翻译文章。
前一阵子给项目增加了翻译的功能,用的是Bing Translator Widget,今天看见有个兄弟写自定义自己的博客,我就尝试着把这个插件加到了自己的博客中.还真的好用.大家先看下效果,觉得好的请继 ...
- React系列文章:Babel编译JSX生成代码
上次我们总结了React代码构建后的Webpack模块组织关系,今天来介绍一下Babel编译JSX生成目标代码的一些规则,并且模拟整个生成的过程. 我们还是拿最简单的代码举例: import {gre ...
- Windows远程桌面,连接被拒绝,因为没有授权此用户帐户进行远程登录。
Windows 服务器远程连接的时候,出现错误:“连接被拒绝,因为没有授权此用户帐户进行远程登录.”,导致无法远程登录服务器,如下图所示: 问题分析 该错误一般是由于 Windows 远程桌面相关权限 ...