所以我将Redis添加到项目中,我正在使用缓存调用包装数据库调用。
如果我在模型中有这样的查询(模型只是将数据返回给控制器):
"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;
更新
countries表只是示例数据,但它表示正在定期读取和写入的任何表。缓存必须始终表示存储在数据库中的内容,因此当我们插入新实体或更新现有实体时,我们也会更新缓存。 缓存中还存储了多个其他密钥和用户数据,并且可能存在缓存驱逐某些密钥的情况,并且对缓存的一些请求可能导致无法找到任何密钥。
我的问题是:您如何保证预期在缓存中找到的数据是: A)在缓存中找到,或者 B)在缓存中找不到,因此我们将其放在缓存中
和
每个从缓存中获取内容的请求是否要求我们运行数据库查询以从数据库中检索数据,然后将其放入缓存中,如上例所示?
答案 0 :(得分:1)
您需要另外考虑,使用cache-aside pattern并使用逻辑从获取操作中的缓存中检索/插入。
请参阅此psedo代码以获取示例(抱歉,我不熟悉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}");
}
因此,您永远不会更新缓存,只需在第一次检索对象时添加到缓存中,并在更新/删除实体后使密钥无效。