zdppy+vue3+onlyoffice文档管理系统实战 20240825上课笔记 zdppy_cache框架增加resize清理缓存的方法

本文主要是介绍zdppy+vue3+onlyoffice文档管理系统实战 20240825上课笔记 zdppy_cache框架增加resize清理缓存的方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

遗留问题

  • 设置缓存,已完成
  • 获取缓存,已实现
  • 删除缓存,已实现
  • 查询所有key,带查询参数:active只查激活的,value包含value默认只获取key
  • 查询缓存大小
  • 清空缓存
  • 判断是否为管理员

实现删除缓存的接口

async def delete(req):"""删除缓存的接口"""data = await api.req.get_json(req)key = data.get("key")admin_cache.delete(key)return api.resp.success()

测试:

req -X DELETE -d '{\"key\":1}' http://127.0.0.1:8888/zdppy_cache

查询缓存接口

基本设计

批量查询缓存信息:
```bash
# 默认查询所有的key,
req  http://127.0.0.1:8888/zdppy_caches# 只查询未过期的keys
req -d '{\"active\":true}' http://127.0.0.1:8888/zdppy_caches# 查看key-value格式
req -d '{\"active\":true, \"value\":true}' http://127.0.0.1:8888/zdppy_caches# 查询详细缓存信息
req -d '{\"active\":true, \"value\":true, \"detail\":true}' http://127.0.0.1:8888/zdppy_caches

先实现默认查询所有的key

async def query(req):"""查询缓存的接口"""params = await api.req.get_json(req)if params.get("error"):params = Nonedata = admin_cache.get_all_keys()return api.resp.success({"query": params,"data": data,})

只查询未过期的

async def query(req):"""查询缓存的接口"""params = await api.req.get_json(req)data = []if params.get("error"):params = None# 查询所有的keydata = admin_cache.get_all_keys()elif params.get("active"):# 只查询未过期的data = admin_cache.get_all_keys(True)return api.resp.success({"query": params,"data": data,})

设置缓存:

req -X POST -d '{\"key\":1,\"value\":111, \"expire\": 1}' http://127.0.0.1:8888/zdppy_cache
req -X POST -d '{\"key\":2,\"value\":222, \"expire\": 2}' http://127.0.0.1:8888/zdppy_cache
req -X POST -d '{\"key\":3,\"value\":333, \"expire\": 333}' http://127.0.0.1:8888/zdppy_cache

先查询所有的key:

req http://127.0.0.1:8888/zdppy_caches

只查询未过期的key:

req -d '{\"active\":true}' http://127.0.0.1:8888/zdppy_caches

自动清理缓存的逻辑

底层核心代码

def _cull(self, now, sql, cleanup, limit=None):"""这个方法是用来清空过期缓存的,无论是否超过限制:param now: 当前时间的秒值,浮点数:param sql: 执行清除的SQL语句:param cleanup: 要清除的文件夹(缓存对象):param limit: 限制多少"""cull_limit = self.cull_limit if limit is None else limitif cull_limit == 0:return# 查询已经过期的keyselect_expired_template = ('SELECT %s FROM Cache'' WHERE expire_time IS NOT NULL AND expire_time < ?'' ORDER BY expire_time LIMIT ?')select_expired = select_expired_template % 'filename'rows = sql(select_expired, (now, cull_limit)).fetchall()if rows:# 如果查询到了就删除delete_expired = 'DELETE FROM Cache WHERE rowid IN (%s)' % (select_expired_template % 'rowid')sql(delete_expired, (now, cull_limit))for (filename,) in rows:cleanup(filename)cull_limit -= len(rows)if cull_limit == 0:return# Evict keys by policy.select_policy = EVICTION_POLICY[self.eviction_policy]['cull']if select_policy is None or self.volume() < self.size_limit:returnselect_filename = select_policy.format(fields='filename', now=now)rows = sql(select_filename, (cull_limit,)).fetchall()if rows:delete = 'DELETE FROM Cache WHERE rowid IN (%s)' % (select_policy.format(fields='rowid', now=now))sql(delete, (cull_limit,))for (filename,) in rows:cleanup(filename)

现在的问题

我们每次set的时候,它都会触发,默认会删除最早过期的十个缓存。

这样不太合理?

因为我只有三个缓存,但是因为过期时间可能比较短,会导致每次set的时候,另一个都可能被删除,这样的库里面找不到全量的记录。

这个方法默认只删除十条,少的时候删除了不爽。多的时候,比如一下子几百个过期,只删除10条好像也没啥用?

你拿过期的缓存来干啥?

  • 1、开发运维的时候可以查询
  • 2、可以感知到别人的攻击,留底别人的记录,比如一下子多了很多失效的验证码,这属于异常数据,可以被分析出来

什么时候清除合适?

  • 1、定时任务,但是这个成本比较高,因为有个定时任务必须随时跑着,可能需要消耗不少系统资源
  • 2、通过物理上限,也就是size_limit这个参数去控制,这个是比较合理的

size_limit 到底有没有生效?

通过全局密码搜索,我们可以发现,只有_cull这个方法用到了size_limit这个参数。
在这里插入图片描述

这段代码是:

# 根据policy执行删除
# least-recently-stored
select_policy = EVICTION_POLICY[self.eviction_policy]['cull']
# 默认是:SELECT {fields} FROM Cache ORDER BY store_time LIMIT ?
if select_policy is None or self.volume() < self.size_limit:return
select_filename = select_policy.format(fields='filename', now=now)
rows = sql(select_filename, (cull_limit,)).fetchall()
if rows:delete = 'DELETE FROM Cache WHERE rowid IN (%s)' % (select_policy.format(fields='rowid', now=now))sql(delete, (cull_limit,))for (filename,) in rows:cleanup(filename)

这里的代码从理论上来说是没啥问题的,但是确实不太符合如下需求:

  • 1、开发运维的时候可以查询已过期的缓存
  • 2、可以感知到别人的攻击,留底别人的记录,比如一下子多了很多失效的验证码,这属于异常数据,可以被分析出来

得出结论:这个方法应该被优化。

怎么优化?

  • 1、set的时候执行的清空缓存的逻辑,没有必要特别的复杂,我们只希望,如果超过了size_limit,则清空缓存。
  • 2、到底清空多少呢?
    • 1、最早过期的10,100,1000条
    • 2、所有已过期的缓存
  • 3、想法:除了最近过期的1000条缓存,其他的都删除!!!

SQL怎么实现清空逻辑

想法:除了最近过期的1000条缓存,其他的都删除!!!

最近的1000条数据的ID。

select id from cache order by add_time desc limit 1000

删除不是这些ID的:ids

delete from cache where id not in ids

核心代码:

DELETE FROM your_table_name WHERE id NOT IN (1, 3, 5);

如果封装成子查询就是:

DELETE FROM your_table_name WHERE id NOT IN (select id from cache order by add_time desc limit 1000);

封装方法

def resize(self):"""根据size_limit缓存上限清理缓存会删除除了最近1000条已过期的缓存以外的其他所有缓存"""child_sql = "SELECT rowid FROM Cache ORDER BY expire_time DESC LIMIT 1000"delete_sql = f'DELETE FROM Cache WHERE rowid NOT IN {child_sql}'self._sql(delete_sql)

测试:sizelimit设置的小一点,比如100。插入2000条1秒过期的数据,查询所有的keys个数。调用resize方法,再查询所有的keys的个数。

from zdppy_cache import Cache# 实例化缓存对象,指定缓存目录
cache = Cache('tmp')
for i in range(2000):cache.set(f"k{i}", i, 1)
print(len(cache.get_all_keys()))cache.resize(1111)
print("resize之后", len(cache.get_all_keys()))# 关闭缓存对象
cache.close()

清除总结

  • 1、delete_all:物理删除,整个文件夹删除
  • 2、delte:删除key对应的
  • 3、resize:只保留最近limit条删除

需求

  • 1、将resize封装为api接口
  • 2、查询所有key,带查询参数:active只查激活的,value包含value默认只获取key
  • 3、查询缓存大小
  • 4、清空缓存
  • 5、判断是否为管理员

这篇关于zdppy+vue3+onlyoffice文档管理系统实战 20240825上课笔记 zdppy_cache框架增加resize清理缓存的方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107899

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

vite搭建vue3项目的搭建步骤

《vite搭建vue3项目的搭建步骤》本文主要介绍了vite搭建vue3项目的搭建步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1.确保Nodejs环境2.使用vite-cli工具3.进入项目安装依赖1.确保Nodejs环境

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

Linux云服务器手动配置DNS的方法步骤

《Linux云服务器手动配置DNS的方法步骤》在Linux云服务器上手动配置DNS(域名系统)是确保服务器能够正常解析域名的重要步骤,以下是详细的配置方法,包括系统文件的修改和常见问题的解决方案,需要... 目录1. 为什么需要手动配置 DNS?2. 手动配置 DNS 的方法方法 1:修改 /etc/res

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat

前端缓存策略的自解方案全解析

《前端缓存策略的自解方案全解析》缓存从来都是前端的一个痛点,很多前端搞不清楚缓存到底是何物,:本文主要介绍前端缓存的自解方案,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、为什么“清缓存”成了技术圈的梗二、先给缓存“把个脉”:浏览器到底缓存了谁?三、设计思路:把“发版”做成“自愈”四、代码