基于内存的类似redis的缓存方法
发表于:2024-11-17 作者:千家信息网编辑
千家信息网最后更新 2024年11月17日,项目中需要用到redis,业务起来之后用到的地方更多,问题来了,因为操作redis太频繁,导致操作redis成为整个项目的瓶颈,经过调研和比较这时候基于内存的cache登场,简单来说就是纯内存层面的c
千家信息网最后更新 2024年11月17日基于内存的类似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安全错误
数据库的锁怎样保障安全
pvg服务器
信息网络安全技术职业教育
网评文章网络安全
企业网络安全防护解决方案
我的世界服务器怎么做
数据库系统的码
酒店的数据库
app控制娃娃机软件开发
软件开发有哪几个过程模式
发现网络安全问题可联系什么
存货软件开发定制方案
库存报警 数据库表
校园网络安全取得的成效报告
网络安全和信息化技术
过好网络安全时代关
江苏现代软件开发配置
免费数据库的资源
药物警戒安全性数据库
软件开发技术方面的院士
软件实施中数据库的安装
tengine服务器安装
镇平系统软件开发公司
我的世界服务器高级附魔书怎么用
中国网络安全与信息化的发展
监督管理厅网络安全检查
东莞量蚁网络技术
石油软件开发电话
数据库系统自动开发
连云港java软件开发
云辰软件开发有限公司