Redisとマングースを用いたキャッシュ層の構築
イントロダクション.
あなたがAPIを構築した場合は、キャッシュを必要とするいくつかの取得要求をキャッシュする必要があります見つける必要があります.本稿ではこの問題の解決策を紹介する.
解決法
我々はここで非常に簡単な戦略に従いますが、始める前に、マングースとノードに精通している必要があります.js
戦略
我々はすべてのブログを取得するクエリを使用して動作しているモデルを想像してください
ブログモデル
const blogSchema = new mongoose.Schema({
owner : {
// user in the database
type: mongoose.Types.ObjectId,
required: true,
ref: "User"
},
title: {
type : String,
required: true
},
tags: {
type : [mongoose.Types.ObjectId],
},
blog: {
type : String
}
});
今すぐすべてのブログを取得するリクエストapp.use("/api/blogs",(req,res,next)=>{
const blogs = await Blogs.find({});
res.send(blogs);
});
我々が我々が働いているもののイメージを得たあと、現在戦略に戻ってくださいここでのトリックは、すべての操作の後に自動的に実行されるマングースの機能があるということです
この関数はexecと呼ばれます.
したがって、キャッシュ・ロジックを行うためにこの
exec
関数を上書きする必要があります.上書きへの第一歩
const exec = mongoose.Query.prototype.exec;
mongoose.Query.prototype.exec = async function (){
// our caching logic
return await exec.apply(this, arguments);
}
今私たちは何がキャッシュされ、何がないかを教えて何かをする必要があります.伝達関数の作成
mongoose.Query.prototype.cache = function(time = 60 * 60){
this.cacheMe = true;
// we will talk about cacheTime later;
this.cacheTime = time;
return this;
}
今私が書いたならBlogs.find({}).cache(); // this is a valid code
今あなたがRedis goに精通していない場合はそれに精通してください.何千ものビデオとチュートリアルがあります、そして、それはその多くの時間をとりません.キャッシュされた結果のデータ構造や型が必要です.いくつかの思考の後、私はこれが最良の構造であることを発見した理由と理由を説明します.
.
ブログのコレクション名です
あなたが
Blogs.find({"title" : "cache" , user : "some id that points to user" })
をしていると言いましょうそれから、クエリーは「タイトル」です:「キャッシュ」、「ユーザー」:「若干のid ...」OP :"クエリのメソッド"を見つける
結果はデータベースから得た結果です
この構造体はnestedashと呼ばれます.
なぜ我々はこのような入れ子のハッシュをやっている
ブログが新しい更新プログラムや挿入や削除操作がキャッシュされた結果を削除した場合、我々は言う必要があります.キャッシュされた結果は古いものであり、新しい操作のいずれかで更新されません.
今すぐコードに戻る。
mongoose.Query.prototype.exec = async function(){
const collectionName = this.mongooseCollection.name;
if(this.cacheMe){
// You can't insert json straight to redis needs to be a string
const key = JSON.stringify({...this.getOptions(),
collectionName : collectionName, op : this.op});
const cachedResults = await redis.HGET(collectionName,key);
// getOptions() returns the query and this.op is the method which in our case is "find"
if (cachedResults){
// if you found cached results return it;
const result = JSON.parse(cachedResults);
return result;
}
//else
// get results from Database then cache it
const result = await exec.apply(this,arguments);
redis.HSET(collectionName, key, JSON.stringify(result) , "EX",this.cacheTime);
//Blogs - > {op: "find" , ... the original query} -> result we got from database
return result;
}
clearCachedData(collectionName, this.op);
return exec.apply(this,arguments);
}
私が更新、挿入または削除の場合、キャッシュされたデータをクリアする必要があると言った部分を覚えておいてください.キャッシュデータをクリアする
async function clearCachedData(collectionName, op){
const allowedCacheOps = ["find","findById","findOne"];
// if operation is insert or delete or update for any collection that exists and has cached values
// delete its childern
if (!allowedCacheOps.includes(op) && await redis.EXISTS(collectionName)){
redis.DEL(collectionName);
}
}
予想結果
はるかに高速クエリを検索します.
キャッシュ
あなたがデータを20 MBまたは100 MBの価値を返す検索クエリがある場合は、あなたのアプリケーション全体を減速されます想像してください.
最終ノート
My redis setup .
Reference
この問題について(Redisとマングースを用いたキャッシュ層の構築), 我々は、より多くの情報をここで見つけました https://dev.to/ahmedmagdy11/building-cache-layer-using-redis-and-mongoose-11kbテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol