首页 > web前端 > js教程 > 正文

使用 Redis 分布式锁构建可扩展的插槽预订系统

Patricia Arquette
发布: 2024-10-22 20:48:28
原创
568 人浏览过

Building a Scalable Slot Booking System with Redis Distributed Locks

在当今快节奏的数字世界中,无缝且可扩展的预订系统至关重要,尤其是当多个用户尝试同时预订同一时段时。本博客概述了使用Redis进行分布式锁定的插槽预订系统的底层设计,这确保用户可以在不遇到竞争条件的情况下预订插槽。通过利用 Redis,我们可以管理并发性和可扩展性,确保我们的预订系统在高需求下高效运行。

系统的关键组件

在深入探讨技术方面之前,我们先来分解一下核心组件:

  1. 用户:代表使用系统预订时段的个人。
  2. Slot:表示用户可以预订的有时限的单元(例如会议室、活动)。
  3. Redis 分布式锁:确保两个用户不能同时预订同一个时段的关键功能。
  4. MongoDB:存储用户和槽位信息。
  5. Redis:充当锁管理器来处理竞争条件。

预订系统的挑战

当多个用户尝试同时预订同一时段时,预订系统很容易陷入重复预订或竞争条件等问题。如果没有适当的并发控制,两个用户可能会无意中预订同一个时段,从而导致沮丧和冲突。

这就是Redis分布式锁发挥作用的地方。使用锁可确保在任何给定时间只有一个用户可以预订时段。


1. 模型:定义用户和槽位

首先,我们需要为用户设计数据模型。这些模型将存储在 MongoDB 中,其结构简单但有效。

一个。 用户模型

每个用户都有基本属性,如姓名、电子邮件和用于身份验证的散列密码:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
    name: { type: String, required: true },
    email: { type: String, required: true, unique: true },
    password: { type: String, required: true },
    createdAt: { type: Date, default: Date.now }
});

module.exports = mongoose.model('User', UserSchema);
登录后复制
登录后复制

b. 老虎机模型

每个时段都有开始和结束时间,并跟踪是否已被预订以及由谁预订:

const mongoose = require('mongoose');

const SlotSchema = new mongoose.Schema({
    startTime: { type: Date, required: true },
    endTime: { type: Date, required: true },
    isBooked: { type: Boolean, default: false },
    bookedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User', default: null }
});

module.exports = mongoose.model('Slot', SlotSchema);
登录后复制

2. API端点:用户如何与系统交互

API是用户和系统之间的桥梁。以下是所需的关键端点:

一个。 用户注册

允许新用户注册:

  • 端点:POST /api/users/register
  • 请求:用户详细信息(姓名、电子邮件、密码)
  • 回复:用户注册确认

b. 用户登录

对用户进行身份验证并提供 JWT 令牌:

  • 端点:POST /api/users/login
  • 请求:用户凭据(电子邮件、密码)
  • 响应:用于身份验证的 JWT 令牌

c. 创建插槽

允许管理员或授权用户创建槽:

  • 端点:POST /api/slots/create
  • 请求:时段开始和结束时间
  • 响应:确认插槽创建

d. 书位

允许用户预订可用时段:

  • 端点:POST /api/slots/book/:id
  • 请求:标头中的 JWT 令牌,URL 中的插槽 ID
  • 响应:时段预订确认或错误(例如,如果时段已被预订)

3.Redis分布式锁的工作原理

并发是预订系统面临的最大挑战。当多个用户尝试同时预订同一个时段时,Redis 会以其分布式锁定功能来救援。

使用Redis锁的预订流程

  1. 锁获取:

    • 当用户尝试预订插槽时,系统会尝试使用 SET lock_key NX EX 10 命令在 Redis 中获取锁。
    • NX(如果不存在则设置)确保仅在锁尚不存在时创建锁,而 EX 10 确保锁在 10 秒后过期(防止死锁)。
    • 如果已经获取了锁,系统会返回 423 Locked 状态,通知用户该槽位已被其他人预订。
  2. 插槽可用性检查

    • 如果成功获取锁,则会查询 MongoDB 以检查该槽是否仍然可用(即未预订)。
    • 如果空位可用,系统会将空位的状态更新为已预订,并将 bookingBy 字段设置为当前用户的 ID。
  3. 锁定释放

    • 一旦预订过程完成,或者发生错误,系统会通过使用 DEL lock_key 命令删除 Redis 密钥来释放锁定。

使用 Redis 锁预订插槽的示例代码:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
    name: { type: String, required: true },
    email: { type: String, required: true, unique: true },
    password: { type: String, required: true },
    createdAt: { type: Date, default: Date.now }
});

module.exports = mongoose.model('User', UserSchema);
登录后复制
登录后复制

4. 预订系统中的错误处理

优雅地处理错误是任何健壮系统的重要组成部分。以下是系统处理的一些错误:

  • 400 Bad Request:当输入数据无效时。
  • 404 Not Found:当未找到请求的槽位或用户时。
  • 423 已锁定:当某个时段当前被其他用户预订时。
  • 500 内部服务器错误:任何意外错误,例如数据库或 Redis 故障。

5. 保护系统安全

安全至关重要,尤其是当用户预订资源时。以下是系统确保安全的方式:

  • JWT 身份验证:每个插槽预订请求都需要有效的 JWT 令牌,确保只有经过身份验证的用户才能访问系统。
  • 数据验证:每一步都会验证输入数据,以防止处理无效或恶意数据。
  • 锁过期:Redis 锁有一个内置的过期时间(10 秒),以防止预订过程中途失败时发生死锁。

6. 可扩展性考虑因素

系统在构建时考虑到了可扩展性。随着需求的增加,以下策略可以确保顺利运营:

  • 用于并发的 Redis:Redis 锁确保即使应用程序的多个实例正在运行,也可以避免竞争条件。
  • Redis Clustering:如果系统显着增长,可以使用Redis Clustering将负载分布到多个Redis节点上,从而提高性能。

结论

构建可扩展且可靠的老虎机预订系统需要仔细考虑并发性、数据完整性和安全性。通过使用Redis分布式锁,我们可以确保没有两个用户同时预订同一个时段,从而消除竞争条件。此外,通过利用MongoDB进行数据持久化和JWT进行身份验证,该系统是安全、可扩展且高效的。

无论您是为会议室、活动还是任何其他有时间限制的资源设计预订系统,此架构都为在重负载下可靠地管理预订提供了坚实的基础。

以上是使用 Redis 分布式锁构建可扩展的插槽预订系统的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!