/opt/utils/cache.js
const Redis = require('ioredis')
const redis = new Redis({
host: "xxx",
port: '6379',
// family: 4,
password: 'xxx',
// db: 0
})
exports.redis = redis
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境
const TcbRouter = require('tcb-router')
const db = cloud.database()
const _ = db.command
const $ = db.command.aggregate
const cache = require('/opt/utils/cache.js') // 使用到了云函数的层管理
const dateUtil = require('/opt/utils/dateUtil.js') // 使用到了云函数的层管理
// 云函数入口函数
exports.main = async (event, context) => {
const app = new TcbRouter({ event })
// const { } = event
const { OPENID, UNIONID } = cloud.getWXContext()
const page = event.page ? Number(event.page) : 0;
const pageSize = event.pageSize ? Number(event.pageSize) : 10;
const skip = page * pageSize
app.use(async (ctx, next) => {
ctx.data = {}
await next();
});
// 1.hot 热门问题(按回答人数)
app.router('hot', async (ctx, next) => {
try {
const date = dateUtil.formatTime(new Date());//当前日期
const cacheKey = `question:hot:${date}:${page}:${pageSize}`
const cacheKeyExists = await cache.redis.exists(cacheKey)
const cacheData = await cache.redis.lrange(cacheKey, 0, -1);
if (cacheKeyExists) {
if (cacheData.length == 1 && cacheData[0] == 'EMPTY') {
// 缓存结果为空
ctx.body = { code: 0, date, cacheKey, msg: '缓存结果空', data: [] }
} else {
// 有缓存
let result = []
for (let index = 0; index < cacheData.length; index++) {
const element = JSON.parse(cacheData[index]);
result.push(element)
}
ctx.body = { code: 0, date, cacheKey, msg: '缓存结果', data: result }
}
} else {
// 从数据库查询数据
const { data } = await db.collection('question').where({
status: 'open',
type: 'public'
}).orderBy('total_answers', 'desc').skip(skip).limit(pageSize).field({
create_time: 1,
title: 1,
total_answers: 1,
total_viewers: 1,
total_collectors: 1,
}).get();
if (data && data.length) {
// 循环遍历存储到redis
for (let index = 0; index < data.length; index++) {
// 时间戳转日期
data[index].create_time = dateUtil.toDate(data[index].create_time)
const element = JSON.stringify(data[index]);
await cache.redis.rpush(cacheKey, element);
await cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
}
} else {
// 数据为空时,设置缓存值为特殊字符串'EMPTY'
await cache.redis.rpush(cacheKey, 'EMPTY', () => {
cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
})
}
ctx.body = { code: 0, date, cacheKey, msg: '数据库结果', data }
}
} catch (error) {
ctx.body = { code: 1, msg: '获取热门问题失败', data: error }
} finally {
cache.redis.disconnect()
}
})
// 2.latest 最新问题
app.router('latest', async (ctx, next) => {
try {
const date = dateUtil.formatTime(new Date());//当前日期
const cacheKey = `question:latest:${date}:${page}:${pageSize}`
const cacheKeyExists = await cache.redis.exists(cacheKey)
const cacheData = await cache.redis.lrange(cacheKey, 0, -1);
if (cacheKeyExists) {
if (cacheData.length == 1 && cacheData[0] == 'EMPTY') {
// 缓存结果为空
ctx.body = { code: 0, date, cacheKey, msg: '缓存结果空', data: [] }
} else {
// 有缓存
let result = []
for (let index = 0; index < cacheData.length; index++) {
const element = JSON.parse(cacheData[index]);
result.push(element)
}
ctx.body = { code: 0, date, cacheKey, msg: '缓存结果', data: result }
}
} else {
// 从数据库查询数据
const { data } = await db.collection('question').where({
status: 'open',
type: 'public'
}).orderBy('create_time', 'desc').skip(skip).limit(pageSize).field({
create_time: 1,
title: 1,
total_answers: 1,
total_viewers: 1,
total_collectors: 1,
}).get();
if (data && data.length) {
// 循环遍历存储到redis
for (let index = 0; index < data.length; index++) {
// 时间戳转日期
data[index].create_time = dateUtil.toDate(data[index].create_time)
const element = JSON.stringify(data[index]);
await cache.redis.rpush(cacheKey, element);
await cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
}
} else {
// 数据为空时,设置缓存值为特殊字符串'EMPTY'
await cache.redis.rpush(cacheKey, 'EMPTY', () => {
cache.redis.expire(cacheKey, 60 * 60 * 24);//24小时过期
})
}
ctx.body = { code: 0, date, cacheKey, msg: '数据库结果', data }
}
} catch (error) {
ctx.body = { code: 1, msg: '获取最新问题失败', data: error }
} finally {
cache.redis.disconnect()
}
})
return app.serve();
}
如上图代码中,每个云函数中 调用cache.redis.disconnect()就能调用成功。
这样做的话会有性能上的影响吗?这样每次调用云函数都要重新连接redis吧?
还是有什么更好的办法忽略掉日志的错误吗?
我觉得在云函数上面使用redis,可能得结合他的运行机制,云函数是无状态的,运行的实例随时会被销毁,所以在上面连接redis,每次请求进来就需要重连一下redis,用完关闭,这样的做法是最稳妥的。
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/mechanism.html
用完就关闭,要不然持续计费到超时时间