- 众所周知,微信有几亿的用户群,某一时刻可能有几千人同时在玩漂流瓶,对于这种高并发数据量小的服务,使用 Node.js 和 Redis 绝对是一个不二的选择;
- 第一步,当然是需要设计好与服务器交互的接口,采用 JSON 形式的 API 接口,因为 Node.js 中对 HTTP 一流的支持,以及对 JSON 的友好让创建 JSON API 变得格外简单;
接口定义
打捞一个漂流瓶
-
以 GET 加参数的形式访问服务器打捞一个漂流瓶,返回 JSON 数据:
// GET /?user=xxx[&type=xxx] // 成功返回 { "code": 1, "msg": { "time": "xxx", "owner": "xxx", "type": "xxx", "content": "xxx" } } // 失败返回 { "code": 0, "msg": "xxx" }
-
GET 请求的参数如下:
- user:捡漂流瓶的人的用户名或用户 id 必须唯一;
- type:漂流瓶类型,这里设置三种类型:all 代表全部,male 代表男性,female 代表女性,默认时为 all;
-
返回的 JSON 参数含义如下:
- code:标识码,1 代表成功,0 代表出错;
- msg:返回的信息,错误时返回错误的信息,成功时返回漂流瓶的信息;
- time:漂流瓶扔出的时间戳;
- owner:漂流瓶主人,可以是用户名或用户 id ,但必须仅有一个;
- type:漂流瓶类型,为 male 或 female 之一;
- content:漂流瓶内容;
扔出一个漂流瓶
-
以 POST 形式请求服务器扔出一个漂流瓶,返回 JSON 数据:
// POST owner=xxx&type=xxx&content=xxx[&time=xxx] // 成功 { "code": 1, "msg": "xxx" } // 失败 { "code": "xxx", "msg": "xxx" }
-
POST 请求的参数如下:
- time:漂流瓶扔出的时间戳,默认时设置为 Date.now();
- owner:漂流瓶主人,可以是用户名或用户 id ,但必须仅有一个;
- type:漂流瓶类型,为 male 或 female 之一;
- content:漂流瓶内容;
-
返回的 JSON 参数含义如下:
- code:标识码,1 代表成功,0 代表出错;
- msg:返回的信息,错误时返回错误的信息,成功时返回漂流瓶的信息;
功能实现
代码实现
-
项目初始化
mkdir drift-bottle cd drift-bottle npm init -y npm i express ioredis uuidv4
-
路由:
const { uuid } = require('uuidv4'); const Redis = require('ioredis'); const express = require('express'); const app = express(); app.use(express.json()); // 创建 Redis 实例 const redis = new Redis(); // 扔一个漂流瓶 app.post('/', async (req, res, next) => { try { const bottle = req.body; // 设置时间戳 bottle.time = bottle.time || Date.now(); // 为每个漂流瓶随机生成一个不重复的id const bottleId = uuid(); const type = { male: 0, female: 1, }; await redis .pipeline() // 根据类型切换数据库 .select(type[bottle.type]) // 将数据存为 Hash .hmset(bottleId, bottle) // 设置 1 天有效期 .expire(bottleId, 24 * 60 * 60) .exec(); res.status(201).json({ bottle: { id: bottleId, ...bottle, }, }); } catch (error) { next(error); } }); // 捡一个漂流瓶 app.get('/', async (req, res, next) => { try { const query = req.query; const type = { all: Math.round(Math.random()), male: 0, female: 1, }; query.type = query.type || 'all'; // 根据类型切换数据库 await redis.select(type[query.type]); // 随机获取一个 key const bottleId = await redis.randomkey(); if (!bottleId) { res.status(200).json({ message: '大海很干净...', }); } // 根据漂流瓶 id 获取完整的漂流瓶信息 const bottle = await redis.hgetall(bottleId); res.status(201).json({ bottle, }); // 从 Redis 中删除捡到的漂流瓶 redis.del(bottleId); } catch (error) { next(error); } }); // 统一处理异常 app.use((err, req, res, next) => { res.status(500).json({ error: err.message, }); }); app.listen(3000, () => { console.log('runnning'); });
接口测试
-
扔一个漂流瓶
-
捡一个漂流瓶
Redis👉 在 Node 中操作 Redis
上一篇