tnfy.link——还有一个用户器?

由于英语不是我的母语,我使用了一些 AI 工具来改进文本,您可以在此处找到原始版本。我很感激您的反馈,您更喜欢哪个版本。

大家好!

开始

这个故事从一个简单的任务开始:我需要创建包含指向我无法控制的服务的链接的帖子,并跟踪该链接的点击次数。

我做的第一件事就是使用 Google 搜索网址缩短服务。我找到了很多选择。但是,有些过于复杂,有些包含广告或需要注册,有些速度慢得令人沮丧。没有一个符合我的要求。

我也在 GitHub 上看到了几个开源项目。但后来我想:我也是一名开发人员。为什么不创建自己的 URL 缩短器呢?它简单、实用,并且能满足我的需求?

我应该使用什么?

由于之前使用过 Go 和 Fiber,选择 Web 堆栈很容易。最初,我尝试了,但遇到了一些限制,例如对子路由器的支持受限。由于我的项目只需要几个 REST 端点(Huma 的优势),所以我决定坚持使用原始 Fiber。

接下来是存储问题——用于映射短链接和长链接以及存储统计数据。由于我没有计划高流量服务,因此我可以使用任何解决方案:RDBMS、NoSQL 或键值存储。

我更喜欢自托管解决方案,因此 Firebase 之类的 SaaS 不在考虑范围内。如果您对本系列感兴趣,我会写一篇关于部署过程的文章。

我看重简单性。存储短长链接对听起来像是一个“键值”用例,所以我选择了**Redis**。

有些人可能认为我选择 Redis 是因为它的速度。你说得对,但并不完全正确。是的,Redis 速度很快,因为它将所有内容都存储在 RAM 中,并且我的服务中的重定向时间不到 1 毫秒。但是,用户的请求仍然必须往返于服务器,这通常会使响应时间增加 50-100 毫秒或更多。在大多数情况下,Redis 的性能优势对于最终用户来说微不足道。

注意:响应时间不仅会影响用户体验,还会影响服务本身。响应时间越短,资源消耗就越少,每秒请求数 (RPS) 就越高。

存储

我将描述我在开发过程中采取的步骤。一些最初的想法并不理想,我将解释原因。

由于我选择了 Redis,所以我的选项仅限于其数据类型。RAM 是有限的,因此我决定为链接添加 7 天的 TTL(生存时间),以便以后灵活调整。

最初,Redis 的 **String** 类型似乎是理想的。像“links:可以将目标 URL 存储为值。诸如 `SET` 和 `NX`(用于防止覆盖)和 `EX`(用于设置 TTL)之类的命令提供了一个简单的解决方案。

但是,如果我将来想存储其他元数据(例如创建日期或用户 ID),该怎么办?我可以创建单独的键(`链接::createdDate`, `链接::userId` 等),但管理跨多个键的 TTL 会变得繁琐且容易出错。

值得庆幸的是,Redis 的 **Hash** 数据类型解决了这个问题。使用哈希,我可以将所有与链接相关的数据存储在一个键下(“links::meta`) 并使用 设置字段。可以使用 将 TTL 应用于整个键,以确保一致性。

但有一个问题:Redis 哈希缺少“NX”选项来防止冲突。在并发环境中,在“HSET”之前使用“EXISTS”检查键是否存在并不可靠。分布式锁可能会有所帮助,但它会降低写入吞吐量。

即使没有高吞吐量要求,我也需要为潜在的负载增加做好计划。

Redis 7.4 引入了一个更好的解决方案:命令。它允许在单个哈希字段上设置 TTL,这对于此用例来说非常完美。

这是我的最终方法:

  • 生成一个 ID,并尝试使用 HSETNX links:index 将 ID-URL 对保存在索引哈希 (links:index) 中 。如果结果为 0,则发生碰撞。
  • 如果成功,则使用 HSET 链接设置元数据::meta 键1 值1 键2 值2 ....
  • 设置 TTLlinks:index 中的字段使用 HEXPIRE links:index ,对于带有 EXPIRE 链接的元数据::meta。
  • 步骤 2 和 3 可以采用流水线方式,以尽量减少与 Redis 的往返次数。

    数据模型

    links
      | index - HASH
          |  -> target URL
      | 
          | meta - HASH
              | targetUrl -> target URL
              | createdAt -> created at date
              | validUntil -> valid until date

    结论

    今天,我们开始设计一个新的 URL 缩短器,并讨论一个关键组件:链接存储。

    如果您对这个项目感兴趣,下一部分将探讨 ID 生成并可能开始编写代码。

    我很想听听您对这个项目的想法和反馈!该服务目前处于 alpha 阶段,但欢迎您随时试用。

    源代码可在 GitHub 上获取:tnfy-link。服务接近测试阶段时将更新文档。

    感谢阅读!