简体中文
新增于HBuilderX 3.5.2,需先开通redis
uniCloud 提供了 MongoDB 和 Redis 2种数据库。并且提供了联动机制,可以方便的将 MongoDB 中的数据缓存到 Redis 中。
适用场景:
需要频繁访问,但不会频繁修改的数据。比如更新不频繁的首页列表、banner、热搜、top排行等公共数据。
这些查询请求频次高,如果每次都去MongoDB读取,又慢又贵,还可能超时或超并发。
使用JQL Cache Redis
,就可以方便的将这些查询结果缓存在 Redis 中。即提升了访问速度,又提升了并发性能,还减少了云函数运行时长和数据库读取次数。
JQL Cache Redis
JQL Cache Redis
需加载 Redis 和 JQL 扩展库,并依赖uni-config-center
公共模块uni-config-center
中配置指定 JQL 查询指令在uniCloud/cloudfunctions/common/uni-config-center
下创建uni-jql-cache-redis.json
文件(注意此文件是标准json格式,不支持注释)
如未安装uni-config-center
,请在插件市场导入,插件地址:uni-config-center
uni-jql-cache-redis.json
文件是一个数组,其中每一项是一个缓存配置。示例内容如下
[{
"id": "test-get", // 缓存id,不可重复,必填
"jql": "db.collection('test').limit(10).get()", // 要缓存的数据库指令,必填
"expiresIn": 3600 // 缓存有效期,单位秒,非必填
}]
expiresIn
是缓存有效期,单位秒,有效期的开始时间为第一次cache到redis的时间(其实就是redis自带的有效期)。如果不填,就意味着不会根据时间失效。
配置成功后,客户端或云端JQL查询db.collection('test').limit(10).get()
时,就会优先去redis中找,如果没找到,会从MongoDB中找然后自动cache到redis中。
命中缓存时,clientDB或使用了jql扩展的云函数/云对象会输出以下日志
"当前请求需使用Redis缓存"
"返回Redis内缓存的结果"
未命中缓存时,clientDB或使用了jql扩展的云函数/云对象会输出以下日志
"当前请求需使用Redis缓存"
"未命中Redis缓存,设置Redis缓存"
JQL Cache Redis
会将缓存配置对应的查询结果缓存到key为unicloud:jql-cache:${id}:string
的redis缓存内。可以在uniCloud web控制台的redis视图中找到。
配置"jql": "db.collection('test').limit(10).get()"
时需注意,普通的JQL语句放在json的value中需要对引号转义,见下。
由于需要将查询语句放在json文件内,而json内字符串又需要引号包围,所以对于查询语句内使用双引号的场景需转义后再放到配置内。
例如:
// jql
db.collection('book').where('author=="caoxueqin"').get()
// 转义后
"db.collection('book').where('author==\"caoxueqin\"').get()"
如果你的查询语句比较复杂,自己一个个加转义符比较麻烦。可以通过如下方式获取转义后的字符串
'use strict';
const fs = require('fs')
const path = require('path')
exports.main = async (event, context) => {
console.log(
fs.readFileSync(
path.resolve(__dirname, 'test.jql')
).toString()
)
};
test.jql
文件,内容为要转义的jql查询语句db.collection('book').where('author=="caoxueqin"').get()
21:56:44.135 [本地运行]"db.collection('book').where('author==\"caoxueqin\"').get()" uniCloud-aliyun/cloudfunctions/test/index.js:5:10
db.getCloudEnv()
或$cloudEnv_
开头的云端环境变量的查询.where('name=="caoxueqin"')
,调用时使用了转义单引号写法,.where('name==\'caoxueqin\'')
,那么这个调用查询就不会走redis缓存。此问题后续优化使用multiSend同时发送多条指令时,不支持将整个multiSend进行缓存。需要单独缓存每条指令。
例:
const book = db.collection('book').limit(10).getTemp()
const author = db.collection('author').limit(10).getTemp()
db.multiSend(book,author)
对上述数据库指令不能直接将缓存配置中的jql配置为const book = db.collection('book').limit(10).getTemp();const author = db.collection('author').limit(10).getTemp();db.multiSend(book,author)
需要单独配置book表的查询语句和author表的查询语句,注意getTemp方法也需要改为get方法
[{
"id": "book-get",
"jql": "db.collection('book').limit(10).get()",
"expiresIn": 3600
}, {
"id": "author-get",
"jql": "db.collection('author').limit(10).get()",
"expiresIn": 3600
}]
联表时配置的缓存语句也和jql语法一致
例:
const book = db.collection('book').limit(10).getTemp()
const author = db.collection('author').getTemp()
db.collection(book, author).get()
uni-jql-cache-redis.json
缓存配置如下
[{
"id": "book-author-lookup",
"jql": "const book = db.collection('book').limit(10).getTemp();const author = db.collection('author').getTemp();db.collection(book, author).get()",
"expiresIn": 3600
}]
当MongoDB中的数据变更时,应该主动删除Redis中的缓存。
比如把banner轮播图的数据缓存在Redis中后,在admin中修改banner,应该同时在云函数中操作redis,将banner的缓存设为失效
使用redis删除命令传入缓存对应的key即可删除缓存。
例:
const redis = uniCloud.redis()
const id = 'banner' // 这个id就是`uni-jql-cache-redis.json`中配置的id
const cacheKey = `unicloud:jql-cache:${id}:string`
await redis.del(cacheKey)