Cloudflare教程(三)- Wokers

Cloudflare 教程(三)- Wokers

上一篇博客Cloudflare 教程(二)-Wokers

需求背景

上一篇博客中,我已经使用 workers 实现了查询节假日的接口,但是有一些需要优化的点,其中一个很大的问题就是 D1 数据库的查询效率和额度问题。
免费计划中,D1 数据库每天的免费查询额度是 500 万行,注意这里是行,不是次。而 KV 数据库是 10 万,这个是读取的键的数量,如果是批量查询,比如一次查询了 10 个键,那就是消耗 10 额度。
问题就在于,我们的节假日查询,都是使用具体的日期查询的,它每次读取的键就是固定的 1 个键,消耗 1 额度。而 D1 数据库则不同,是行按查询的行数消耗额度。同时,由于我们一开始设计的时候使用了一个无效的字段(id)作为主键,在代码逻辑中它其实并没有任何用处,并且我们的 date 字段其实并不会重复,完全可以使用 date 字段作为主键,以减少查询的行数。所以现在的情况就是,每次查询都会扫全表,成百倍的放大查询额度消耗(我已经将 2023,2024,2025 年的数据存入到了 D1 中,有 100+条数据)。

这样子的话,D1 的 500 万额度,其实也就相当于 5 万而已,而 KV 的 10 万额度,反而更多一些了。如果数据量再大一些,这个差距会更大。这都源于表字段设计之后的考虑不周,不过我也不打算再去修复这个问题了(换成 date 字段作为主键,就能解决这个问题),用上 KV 算是稍微修补一下吧,也正好学习 KV 的使用。

百倍消耗的原因在于,date 不是主键,它可能重复,所以查询任何一个日期,都会扫全表,而且如果该日期不存在,也一定会扫描全表,从概率上来讲一年中的绝大多数日期,都不是节假日,不存在于表中,这些非节假日的日期查询,都会扫全表。

技术选型

  • Cloudflare 的 Wokers
  • ChinaHolidayAPI
  • D1 SQL 数据库 – 这相当于 MySQL
  • Workers KV 数据库 – 这相当于 redis

优化过程

缓存数据到 KV

首先我们需要将处理完成后的数据缓存到 KV 中,这样,下次查询的时候,就可以直接从 KV 中获取数据,而不需要再次查询 D1。这个时机就是在接口返回之前去做缓存,不能提前缓存,以确保存入的数据是正确的。

workers 中使用 KV 可以参考文档:https://developers.cloudflare.com/kv/api/write-key-value-pairs/

配置 KV 数据库

前面我们已经创建过 KV 数据库,这里直接使用它。在 wrangler.jsonc 文件中添加以下配置:

1
2
3
4
5
6
"kv_namespaces": [
{
"binding": "你代码中使用的变量名",
"id": "KV数据的id"
}
]

缓存数据

添加缓存代码:

1
await env.n8n_kv.put("wooapi-holidays" + dateParam, JSON.stringify(result));

效果如下:

npx wrangler deploy部署一下,此时我们请求一下接口,可以看到 KV 中已经缓存了数据了。

https://wooapi.664663.xyz/holidays?date=2025-05-05

我们可以在后台查询到,该日期的数据已经缓存到了 KV 中。

读取数据

参考文档:https://developers.cloudflare.com/kv/api/read-key-value-pairs/

在我们校验日期格式有效之后,我们尝试从 KV 中获取数据:

1
await env.NAMESPACE.get(key);

此时我们的代码如下:

需要注意的点:

  1. 获取数据要记得判断空值,如果 key 不存在,则返回 null,走 D1 数据库查询逻辑;
  2. 如果不为空值,则要进行 JSON.parse()操作;
  3. 特别要注意,截图中第一个箭头的位置,前面我就漏掉了这个操作,在查询到该日期是普通的周末或者工作日的时候,我们提前 return 了数据,这里也应该进行缓存。

此时,可以去 workers 后台,进行实时编辑代码,加日志测试。

你可以换一个没有缓存过的日期,确认是否先输出从 D1 获取数据,然后再次请求,输出从 KV 获取数据,以确保我们使用上了 KV 缓存。记得在左侧的编辑界面修改了代码,点击 ctrl+s 进行保存,再在右侧点击前往或刷新按钮进行测试。

至此,接口已经使用上了 KV 缓存,额度消耗会降低,以及运行效率也会提升。

总结

cloudflare 的 workers 部分,我感觉能结合用上的东西,都实现的差不多了,多看看文档,能了解更多 D1 和 KV 的用法,他们十分强大,cloudflare 这个大善人也很慷慨,我们能用它做很多的功能。如果只是自己使用,额度也完完全全能够满足需求。一切都是那么美好~