防止 Redis 密钥逐出策略
Protect Against Redis Key Eviction Policy
所以我正在将 Redis 添加到一个项目中,并且我正在用缓存调用包装数据库调用。
如果我在模型中有这样的查询(并且模型只是 returns 控制器的数据):
"SELECT * FROM countries";
我的计划是将每个国家缓存在这样的数据结构中:
$cache->hmset("country:1", ['id' => 1, name => 'Ireland']);// 250+ more countries
还要维护国家/地区 ID 的 SET 数据结构,如下所示:
$cache->sadd("countries", 1);
问题
在检索所有国家的情况下,我是否需要编写逻辑来填充两个 redis 数据结构,以防它们中的任何一个不在缓存中?
例如,我的国家模型应该是这样的:
// Check cache for set of valid countries IDs
if (!$cache->exists("countries")) {
$ids = "SELECT id FROM countries";// Pretend $ids is array for simplicity
// Add countries IDs into cache
$cache->sadd("countries", $ids);
}
/* At this point we know the set of country IDs exists */
$country_ids = $cache->smembers("countries");
$response = [];
/* Retrieve each country */
foreach ($country_ids as $id) {
/* If "countries:{$id}" is not in cache */
if (!$cache->exists("countries:{$id}")) {// Retrieve country from database
$entity = "SELECT * FROM countries WHERE countries.id = {$id}";// Pretend $entity is array of fields for simplicity
// Set country entity into cache
$cache->hset("countries:{$id}", $entity);
} else {
$entity = $cache->hgetall("countries:{$id}");
}
$response[] = $entity;
}
return $response;
更新
国家 table 只是样本数据,但它代表任何 table 正在定期读取和写入的数据。缓存必须始终代表数据库中存储的内容,因此当我们插入新实体或更新现有实体时,我们也会更新缓存。
缓存中还存储了多个其他密钥和用户数据,并且可能会出现缓存逐出某些密钥的情况,并且某些对缓存的请求可能会导致找不到任何内容。
我的问题是:您如何保证预期在缓存中找到的数据是:
A)在缓存中找到,或
B) 在缓存中找不到,所以我们把它放在缓存中
和
是否每个从缓存中获取内容的请求都需要我们 运行 数据库查询以从我们的数据库中检索数据,然后将其放入缓存中,如上例所述?
您需要换个思路,使用 cache-aside pattern 并在 Get 操作中具有从缓存中 retrieve/insert 的逻辑。
查看此伪代码示例(抱歉,我不熟悉 php):
function GetCountry($id)
{
if ($cache->hexists("countries:{$id}")) {
$entity = $cache->hgetall("countries:{$id}");
}
else
{
$entity = $database.GetCountry($id);
$cache->hmset("country:{$id}", ['id' => $entity->id, ... ]);
}
return $entity;
}
function AddCountry($country)
{
$database.AddCountry($country);
}
function UpdateCountry($id, $data)
{
$database.UpdateCountry($id, $data);
$cache->del("country:{$id}");
}
function DeleteCountry($id)
{
$database.DeleteCountry($id);
$cache->del("country:{$id}");
}
所以你永远不会更新缓存,你只是在第一次检索对象时添加到缓存,并在updating/deleting实体之后使键无效.
所以我正在将 Redis 添加到一个项目中,并且我正在用缓存调用包装数据库调用。
如果我在模型中有这样的查询(并且模型只是 returns 控制器的数据):
"SELECT * FROM countries";
我的计划是将每个国家缓存在这样的数据结构中:
$cache->hmset("country:1", ['id' => 1, name => 'Ireland']);// 250+ more countries
还要维护国家/地区 ID 的 SET 数据结构,如下所示:
$cache->sadd("countries", 1);
问题
在检索所有国家的情况下,我是否需要编写逻辑来填充两个 redis 数据结构,以防它们中的任何一个不在缓存中? 例如,我的国家模型应该是这样的:
// Check cache for set of valid countries IDs
if (!$cache->exists("countries")) {
$ids = "SELECT id FROM countries";// Pretend $ids is array for simplicity
// Add countries IDs into cache
$cache->sadd("countries", $ids);
}
/* At this point we know the set of country IDs exists */
$country_ids = $cache->smembers("countries");
$response = [];
/* Retrieve each country */
foreach ($country_ids as $id) {
/* If "countries:{$id}" is not in cache */
if (!$cache->exists("countries:{$id}")) {// Retrieve country from database
$entity = "SELECT * FROM countries WHERE countries.id = {$id}";// Pretend $entity is array of fields for simplicity
// Set country entity into cache
$cache->hset("countries:{$id}", $entity);
} else {
$entity = $cache->hgetall("countries:{$id}");
}
$response[] = $entity;
}
return $response;
更新
国家 table 只是样本数据,但它代表任何 table 正在定期读取和写入的数据。缓存必须始终代表数据库中存储的内容,因此当我们插入新实体或更新现有实体时,我们也会更新缓存。 缓存中还存储了多个其他密钥和用户数据,并且可能会出现缓存逐出某些密钥的情况,并且某些对缓存的请求可能会导致找不到任何内容。
我的问题是:您如何保证预期在缓存中找到的数据是: A)在缓存中找到,或 B) 在缓存中找不到,所以我们把它放在缓存中
和
是否每个从缓存中获取内容的请求都需要我们 运行 数据库查询以从我们的数据库中检索数据,然后将其放入缓存中,如上例所述?
您需要换个思路,使用 cache-aside pattern 并在 Get 操作中具有从缓存中 retrieve/insert 的逻辑。
查看此伪代码示例(抱歉,我不熟悉 php):
function GetCountry($id)
{
if ($cache->hexists("countries:{$id}")) {
$entity = $cache->hgetall("countries:{$id}");
}
else
{
$entity = $database.GetCountry($id);
$cache->hmset("country:{$id}", ['id' => $entity->id, ... ]);
}
return $entity;
}
function AddCountry($country)
{
$database.AddCountry($country);
}
function UpdateCountry($id, $data)
{
$database.UpdateCountry($id, $data);
$cache->del("country:{$id}");
}
function DeleteCountry($id)
{
$database.DeleteCountry($id);
$cache->del("country:{$id}");
}
所以你永远不会更新缓存,你只是在第一次检索对象时添加到缓存,并在updating/deleting实体之后使键无效.