Redis: ภาพรวม
Redis = in-memory data structure store ใช้เป็น database, cache, message broker รองรับ strings, hashes, lists, sets, sorted sets, streams, geospatial, bitmaps, hyperloglogs
การ Implement Caching ใน Express + Mongoose
เชื่อมต่อ Redis
const redis = require('redis');
const util = require('util');
const redisUrl = 'redis://127.0.0.1:6379';
const client = redis.createClient(redisUrl);
client.hget = util.promisify(client.hget);
Override Mongoose exec() เพื่อ Caching แบบ Reusable
const exec = mongoose.Query.prototype.exec;
mongoose.Query.prototype.exec = async function() {
if (!this.enableCache) {
console.log('Data Source: Database');
return exec.apply(this, arguments);
}
const key = JSON.stringify(Object.assign({}, this.getQuery(), {
collection: this.mongooseCollection.name
}));
const cachedValue = await client.hget(this.hashKey, key);
if (cachedValue) {
const parsedCache = JSON.parse(cachedValue);
console.log('Data Source: Cache');
return Array.isArray(parsedCache)
? parsedCache.map(doc => new this.model(doc))
: new this.model(parsedCache);
}
const result = await exec.apply(this, arguments);
client.hmset(this.hashKey, key, JSON.stringify(result), 'EX', 300); // 5 นาที
console.log('Data Source: Database');
return result;
};
Cache Query Helper
mongoose.Query.prototype.cache = function(options = {}) {
this.enableCache = true;
this.hashKey = JSON.stringify(options.key || 'default');
return this;
};
ใช้งาน: Blog.find({ user: req.params.user }).cache({ key: req.params.user })
Forced Cache Expiration (เมื่อสร้าง Blog ใหม่)
// services/cache.js
module.exports = {
clearCache(hashKey) {
console.log('Cache cleaned');
client.del(JSON.stringify(hashKey));
}
};
// Middleware
module.exports = async (req, res, next) => {
await next();
clearCache(req.body.user);
};
// ใช้ใน route
blogsRouter.route('/').post(cleanCache, async (req, res, next) => { ... });
ผลลัพธ์จริง (Postman)
- Query ครั้งแรก (Database): ~409ms
- Query ครั้งที่สอง (Cache): ~24ms
- ลดเวลา 95%
สรุป
Caching เป็นขั้นตอนบังคับสำหรับแอป data-intensive Redis ทำได้ง่าย อีกพลัง และ reusable ผ่าน Mongoose middleware โค้ดเต็มใน repo redis-express