此代码在本地运行没有任何问题,但在部署到 Vercel 上时会挂起。当我在Upstash中查看Redis监控时,发现有时数据插入成功,有时则插入失败。 Vercel 上的日志显示,有时代码会通过await 语句,但有时会卡在await 处。
我使用 Upstash 的 Redis 进行即用即付计划,使用 Vercel 进行 Pro 计划。
我也在使用Upstash的QStash,我也遇到了类似的问题。有时它会成功触发,而有时它会在第一次调用时卡住。所有这些操作在本地运行时都可以正常工作。
import { Redis } from '@upstash/redis'
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
enableAutoPipelining: true,
retry: {
retries: 5,
backoff: (retryCount) => Math.exp(retryCount) * 50,
},
})
const result = await Promise.all([
redis.hset(taskId + '_info', {platform,searchId,collectionId,}),
redis.rpush(taskId, ...keywords),
redis.expire(taskId, TASK_EXPIRY_TIME),
redis.expire(taskId + '_info', TASK_EXPIRY_TIME)
]);```
我尝试了多种解决方案来解决此问题:
调整Vercel的函数执行时间:我尝试在Vercel的设置中增加函数超时,但这并没有解决挂起的问题。
使用Redis管道:我尝试使用Redis管道将多个命令一起批处理,如下所示:
const pipeline = redis.pipeline();
pipeline.hset(taskId + '_info', { /* data */ });
pipeline.rpush(taskId, ...keywords);
pipeline.expire(taskId, TASK_EXPIRY_TIME);
pipeline.expire(taskId + '_info', TASK_EXPIRY_TIME);
const results = await pipeline.exec();
但是,这种方法在某些情况下仍然会导致相同的挂起行为。
启用自动流水线后,您提供的代码示例实际上是等效的。
您可以尝试以下两件事:
const hsetResult = await redis.hset(taskId + '_info', {platform,searchId,collectionId,})
const rpushResult = await redis.rpush(taskId, ...keywords)
const expireResult = await redis.expire(taskId, TASK_EXPIRY_TIME)
const expireResult2 = await redis.expire(taskId + '_info', TASK_EXPIRY_TIME)
此代码远非理想,因为它会导致多个请求,但可以帮助您调试错误。
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
enableAutoPipelining: true,
retry: false
})