基于内存的类似redis的缓存方法
发表于:2024-10-04 作者:千家信息网编辑
千家信息网最后更新 2024年10月04日,项目中需要用到redis,业务起来之后用到的地方更多,问题来了,因为操作redis太频繁,导致操作redis成为整个项目的瓶颈,经过调研和比较这时候基于内存的cache登场,简单来说就是纯内存层面的c
千家信息网最后更新 2024年10月04日基于内存的类似redis的缓存方法
项目中需要用到redis,业务起来之后用到的地方更多,问题来了,因为操作redis太频繁,导致操作redis成为整个项目的瓶颈,经过调研和比较这时候基于内存的cache登场,简单来说就是纯内存层面的cache,可以实现
1、缓存数量的限制(不能无限制的堆内存,会撑爆)
2、能设置过期时间(内存中只缓存高频出现的数据)
放上业务流程的对比图,就是在redis之前加了一层,比较redis虽然基于内存但是连接包括操作还是得产生网络io操作
下面是我做的对比测试:
普通数据:
1、假设全部不命中(内存和redis都没有): [root@master test]# python 6.py 这是100次的结果 内存:[0.006078958511352539, 0.00607609748840332, 0.006433963775634766] redis:[0.00573420524597168, 0.007025003433227539, 0.005178928375244141] 这是1000次的结果 内存:[0.07438397407531738, 0.07421493530273438, 0.0615389347076416] redis:[0.04864096641540527, 0.04749107360839844, 0.05013895034790039] 这是10000次的结果 内存:[0.5369880199432373, 0.48474812507629395, 0.4684739112854004] redis:[0.4230480194091797, 0.5131900310516357, 0.43289995193481445] 这是100000次的结果 内存:[5.565299987792969, 5.5354228019714355, 5.658163070678711] redis:[4.795120000839233, 5.0205230712890625, 4.469913005828857]2、假设全部命中: [root@master test]# python 6.py 这是100次的结果 内存:[0.00040602684020996094, 0.00021195411682128906, 0.00021600723266601562] redis:[0.005956888198852539, 0.005934000015258789, 0.005537986755371094] 这是1000次的结果 内存:[0.0021610260009765625, 0.0020508766174316406, 0.002026081085205078] redis:[0.0546720027923584, 0.04969382286071777, 0.04725193977355957] 这是10000次的结果 内存:[0.014709949493408203, 0.01748490333557129, 0.016735076904296875] redis:[0.500324010848999, 0.6110620498657227, 0.5946261882781982] 这是100000次的结果 内存:[0.20346498489379883, 0.20162200927734375, 0.15467381477355957] redis:[5.065227031707764, 5.543213844299316, 5.167007207870483]
json格式的数据:
1、假设全部不命中: [root@master test]# python json_test.py 这是100次的结果 内存 [0.00627589225769043, 0.006350040435791016, 0.006167888641357422] redis [0.00538182258605957, 0.005352973937988281, 0.005239009857177734] 这是1000次的结果 内存 [0.06096196174621582, 0.05894589424133301, 0.0531618595123291] redis [0.04534316062927246, 0.04644417762756348, 0.042047977447509766] 这是10000次的结果 内存 [0.526871919631958, 0.49242496490478516, 0.54292893409729] redis [0.46350693702697754, 0.5339851379394531, 0.514045000076294] 这是100000次的结果 内存 [5.3060479164123535, 5.807142972946167, 4.886216163635254] redis [4.287613153457642, 4.528016090393066, 5.158953905105591]2、假设全部命中: [root@master test]# python json_test.py 这是100次的结果 内存 [0.0005319118499755859, 0.0003058910369873047, 0.0002970695495605469] redis [0.006021022796630859, 0.005857944488525391, 0.006082773208618164] 这是1000次的结果 内存 [0.0028162002563476562, 0.002669811248779297, 0.0026869773864746094] redis [0.07850098609924316, 0.06138491630554199, 0.05786609649658203] 这是10000次的结果 内存 [0.02676105499267578, 0.026623010635375977, 0.026623010635375977] redis [0.6534669399261475, 0.6395609378814697, 0.47389698028564453] 这是100000次的结果 内存 [0.20687103271484375, 0.20745611190795898, 0.19935917854309082] redis [5.537367105484009, 5.8351359367370605, 4.935602903366089]
可以看到,当全部不命中(实际情况只有在第一次才会出现,不然也不用加redis了)的情况下,基于内存和基于redis的性能基本相同,但如果命中过之后这个性能就有很大提升了
直接上代码:
#!/usr/bin/env python# -*- coding:utf8 -*-'''Author : mafeiDate : 2019-09-26'''import timeimport weakrefimport collectionsimport ujson as jsonclass Base(object): notFound = {} class Dict(dict): def __del__(self): pass def __init__(self, maxlen=10): self.weak = weakref.WeakValueDictionary() self.strong = collections.deque(maxlen=maxlen) @staticmethod def now_time(): return int(time.time()) def get(self, key): v = self.weak.get(key, self.notFound) if (v is not self.notFound): expire = v[r'expire'] if (self.now_time() > expire): self.weak.pop(key) return self.notFound else: return v else: return self.notFound def set(self, key, value): self.weak[key] = strongRef = Base.Dict(value) self.strong.append(strongRef)class MemoryCache(object): def __init__(self, maxlen=1000 * 10000, life_cycle=5*60): self.memory_cache = Base(maxlen=maxlen) self.maxlen = maxlen self.life_cycle = life_cycle @staticmethod def _compute_key(key): return key def get(self, k): memory_key = self._compute_key(k) result = self.memory_cache.get(memory_key).get('result', None) if result is None: return result return result def set(self, k, v, life_cycle=None): self._set_memory(k, v, life_cycle) def get_json(self, key): res = self.get(key) try: return json.loads(res) except: return res def set_json(self, k, v, life_cycle=None): try: v = json.dumps(v) except: pass self.set(k, v, life_cycle) def set_with_lock(self, k, v, life_cycle=None): self._set_memory(k, v, life_cycle) def _set_memory(self, k, v, life_cycle=None): life_cycle = life_cycle or self.life_cycle memory_key = self._compute_key(k) self.memory_cache.set(memory_key, {'ip': k, r'result': v, r'expire': life_cycle + self.memory_cache.now_time()})
调用时只需要传入2个参数:
maxlen : 内存中最多缓存多少条数据
life_cycle: 数据失效时间
优点:
1、高效,比直接调用redis要快很多
2、不会产生网络io和磁盘io
缺点:
1、支持的结构比较单一,当然这个可以自己扩充方式实现
2、如果要更新内存中的值不太方便,可以有其他方式实现
内存
结果
这是
数据
缓存
业务
就是
性能
情况
方式
时间
网络
项目
很大
普通
相同
频繁
不用
业务流程
代码
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网络数据库应用系统开发实用教程
徐秋亮网络安全
数据库e-r图
网络安全事关国家安全国际
江西九江电信网络安全工程师工资
零基础云计算网络安全培训学校
牌张数据库
计算机网络安全的可控性
微信如何设置无法连接服务器
数据库字母转换大写
关于网络安全的重要性
企业网络安全工作会议
网络安全检查工作规范
怎样设置数据库字段
软件开发专业山东分数线
北京戴尔服务器虚拟化安装
客户管理系统服务器搭建
安徽服务器机柜订做
nsqip 数据库
在sql中数据库管理系统的特点
网络安全小组的源码
讯泰软件开发有限公司
服务器文件安全性配置文件
查询数据库为空的数据库
北京健康宝的网络安全由谁负责
闻泰科技服务器客户有哪些
项目经理软件开发时间节点
检察院 网络安全检查
服务器好卖吗
哪家云盘做远程数据库好