我正在尝试制作一个小型快速应用程序,它从 postgres 查询返回数据。 查询结果应缓存在 Redis 数据库中。我所做的是这样的:
app.get('/query_tile/:z/:x/:y', async (req: Request, res: Response) => {
const client = new Client(connection);
await client.connect();
const setHeader = () => {
res.set('Content-Encoding', 'br');
res.set('Content-Type', 'application/x-protobuf');
res.set('Vary', 'Origin, Access-Control-Request-Method, Access-Control-Request-Headers');
res.set('Content-Disposition', `attachment; filename=tile_${z}_${x}_${y}.mvt`);
}
const { z, x, y } = req.params;
const cacheKey = `tile_${z}_${x}_${y}`;
const cachedData = await redis.get(cacheKey);
if (cachedData) {
setHeader()
res.send(brotliCompressSync(cachedData));
} else {
const { rows } = await client.query('SELECT query_tile($1, $2, $3)', [z, x, y]);
const data = rows[0];
const compressedData = brotliCompressSync(data.query_tile);
await redis.set(cacheKey, data.query_tile);
setHeader()
res.send(compressedData);
}
client.end()
});
我遇到的问题是,缓存的结果与未缓存的结果不同。 我在这里缺少什么?
两个返回都包含一些数据,但缓存中的数据不可读。至少不是我所需要的。
非常感谢您的帮助!
编辑:如果我尝试将压缩数据保存到 Redis 服务器,如下所示:
let cachedData = null;
if (useCache) {
cachedData = await redis.get(cacheKey);
}
if (cachedData) {
const t1 = performance.now()
console.log(`SENDING CACHED tile_${z}_${x}_${y}, took ${(t1 - t0) / 1000}s`);
setHeader()
res.send(cachedData);
} else {
const { rows } = await client.query('SELECT query_tile($1, $2, $3)', [z, x, y]);
const data = rows[0];
const compressedData = brotliCompressSync(data.query_tile);
await redis.set(cacheKey, compressedData);
const t1 = performance.now()
console.log(`SENDING DB tile_${z}_${x}_${y}, took ${(t1 - t0) / 1000}s`);
setHeader()
res.send(compressedData);
}
我确实遇到了奇怪的行为 - 浏览器告诉我应该检查我的互联网连接
但这仅发生在磨损的瓷砖上。如果没有可用的缓存,它会正确下载图块。
使用“Redis Insight”检查redis服务器,它显示有我的二进制形式的chached磁贴。 (但它仍然在左边说字符串......这应该是这样的吗?)
您正在缓存的数据是二进制数据还是 brotliCompressSync 函数返回纯文本?对我来说看起来像是二进制数据。
如果这是正确的,则在将二进制数据写入 Redis 时需要使用 Buffer,并且在读取时需要使用一点额外的语法,以便它知道返回 Buffer。
默认情况下,它将返回 ASCII 编码的文本,如下所示:
\xff\x00\xd8\xae\xa5x\x80J\xd2\x1c\x0c\x1ay\x89RZ\xd1\x1a\x029\xb7\x1a\xf3\xc5\xd4\x11s(...
您的代码可能如下所示:
// setting binary data, assumes that brotliCompressSync returns a Buffer
const compressedData: Buffer = brotliCompressSync(data.query_tile);
await redis.set(cacheKey, compressedData);
// getting binary data
const cachedData = await redis.get(
commandOptions({ returnBuffers: true }),
cacheKey
);
希望这有帮助!