基于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数据 ...
随机推荐
- python 全栈开发,Day59(小米商城)
一.小米商城 准备工作: 访问iconfont,官网链接: http://www.iconfont.cn/ 登录之后,找到需要的图标 将图标下载到本地,解压,重命名为font创建几个空文件夹:css, ...
- Android Rom build.prop文件详解
# begin build properties # autogenerated by buildinfo.sh #以下内容由脚本在编译时自动产生 ro.build.id=6.7.7_97 ...
- Docker 容器中无ss命令解决方法
在早期运维工作中,查看服务器连接数一般都会用netstat命令.其实,有一个命令比netstat更高效,那就是ss(Socket Statistics)命令!ss命令可以用来获取socket统计信息, ...
- HTML+CSS,让div在屏幕中居中(水平居中+垂直居中)方法总结
最近写网页经常需要将div在屏幕中居中显示,遂记录下几个常用的方法,都比较简单. 水平居中直接加上<center>标签即可,或者设置margin:auto;当然也可以用下面的方法 下面说两 ...
- HDU 3761 炸碉堡【半平面交(nlogn)】+【二分】
<题目链接> < 转载于 > 题目大意: 给出一个凸多边形,顶点为一些防御塔,保护范围是凸多形内部,不包括边界,在多边形内部选择一点,使得对方至少需要摧毁的塔防数量最多 ...
- Linux学习之文件系统常用命令(七)
Linux文件系统常用命令 目录 df命令 du命令 fsck命令 dump2fs命令 df命令 df命令 统计文件系统的占有情况,分区用了多少空间,还剩多少空间 df [选项] [挂载点] 选项: ...
- 局域网下ARP欺骗、嗅探,以及DNS欺骗
准备:kali.xp kali ip:192.168.14.157 目标ip:192.168.14.158 目标网关:192.168.14.2 ARP欺骗:arpspoof -t 目标ip -r 目标 ...
- 不会python?那就换一种姿势爬虫!Java爬虫技术总结
-本博客为原创内容,转载需注明本人- 前几天有个师妹将要毕业,需要准备毕业论文,但是论文调研需要数据资料,上知网一查,十几万条数据!指导老师让她手动copy收集,十几万的数据手动copy要浪费多少时间 ...
- SQLite中的FROM子句
SQLite中的FROM子句 FROM子句从数据库中可以获取到一个或多个源表.源表通常是数据库命名的表,但也可以是视图或子查询.子查询相关的更多详细信息,我们会在后面进行介绍.当获取到多个源表时,JO ...
- JS的prototype和__proto__(含es6的class)
JS的prototype和__proto__(含es6的class) 一.prototype和__proto__的概念 prototype是函数的一个属性(每个函数都有一个prototype属性),这 ...