缓存数据库中是否存在项目

时间:2018-11-19 15:56:15

标签: node.js caching redis

我有一个简单的缓存机制,该机制涉及检查项目是否在数据库缓存(table:id#id_number)中,如果不是,则检查该项目是否在数据库中。如果它在数据库中,那么我将缓存该项目。如果不是,那么我显然不会。

问题是,在我目前的情况下,这种情况会经常发生。每次有人访问首页时,我都会看到id 10是否存在,id 9是否存在,等等。

如果id 9不存在,则将不会缓存任何内容,并且每次有人访问我的首页时,我的服务器将不断访问我的数据库。

我现在的解决方案非常脏,将来很容易导致混乱。我现在正在缓存数据库可能中是否存在一个ID(pexists:table:id#id_number)。如果它可能不存在,我只是假设它不存在,或者未设置缓存。如果它确实存在,我检查它是否在缓存中。如果不是,那么我只会在 then 命中我的数据库。然后,我将从数据库中缓存结果以及该结果是否存在。

我在问是否有更好的方法来达到这种效果。

             /* 
             This method takes an amount (how many posts you need) and start
             (the post id we want to start at). If, for example,
             the DB has ids 1, 2, 4, 7, 9, and we ask for
             amount=3 and start=7, we should return the items
             with ids 7, 4, and 2. 
            */
            const parametersValidity = await this.assureIsValidPollsRequestAsync(
                amount,
                start
            );
            const validParameters = parametersValidity.result;
            if (!validParameters) {
                throw new Error(parametersValidity.err);
            }

            let polls = [];
            for (   
                    let i=start, pollId=start; 
                    (i > start - amount && pollId > 0); 
                    i--, pollId--
            ) {
                // There is probably no poll logged in the database.
                if(!(await this.pollProbablyExists(pollId))) {
                    i++;
                    continue;
                }

                let poll;
                const cacheHash = `polls:id#${pollId}`;
                if(await cache.existsAsync(cacheHash)) {
                    poll = 
                        await this.findKeysFromCacheHash(
                            cacheHash, 
                            "Id", "Title", "Description", "Option1", "Option2", "AuthorId"
                        );
                } else {
                    // Simulates a slow database retreival thingy
                    // for testing.
                    await new Promise(resolve => {
                        setTimeout(resolve, 500)
                    });

                    poll = await this.getPollById(pollId);

                    if(typeof poll !== "undefined") {
                        this.insertKeysIntoCacheHash(
                            cacheHash, 60 * 60 * 3 /* 3 hours to expire */,
                            poll
                        );
                    }
                }
                if(typeof poll === "undefined") {
                    // This would happen if a user deleted a poll
                    // when the exists:polls:id#poll_id key in cache
                    // hadn't expired yet.
                    cache.setAsync(`exists:${cacheHash}`, 0);
                    cache.expire(`exists:polls:id#${pollId}`, 60 * 60 * 10 /* 10 hours. */);
                    i++;
                } else {
                    polls.push(poll);
                    cache.setAsync(`exists:${cacheHash}`, 1);
                }
            }
            return polls;

1 个答案:

答案 0 :(得分:0)

如果我理解正确,则希望避免那些不存在的键频繁击中数据库。

如果是这样,一种更好,更简单的方法是缓存不存在的密钥。

  • 如果密钥存在于数据库中,则可以使用从数据库获取的值将其缓存在Redis中。
  • 如果密钥在数据库中不存在,也可以将其缓存在Redis中,但是具有 special 值。

例如,您将玩家的得分缓存在Redis中。如果播放器不存在,您也可以缓存键,但是以 -1 作为得分。搜索高速缓存时,如果键存在但高速缓存的值为 -1 ,则表示该键在数据库中不存在。