redis 作 mysql 缓存_MySQL数据库之初学Redis(2)——用Redis作为Mysql数据库的缓存...

本文主要向大家介绍了MySQL数据库之初学Redis的用Redis作为Mysql数据库的缓存,通过具体的实例让大家了解,希望对大家学习MySQL数据库有所帮助。

用Redis作MySQL数据库缓存,必须解决2个问题。首先,应该确定用何种数据结构存储来自mysql的数据;在确定数据结构之后,还要考虑用什么标识作为该数据结构的键。

直观上看,Mysql中的数据都是按表存储的;更微观地看,这些表都是按行存储的。每执行一次select查询,Mysql都会返回一个结果集,这个结果集由若干行组成。所以,一个自然而然的想法就是在redis中找到一种对应于Mysql行的数据结构。Redis中提供了五种基本数据结构,即字符串(string)、列表(list)、哈希(hash)、集合(set)和有序集合(sorted set)。经过调研,发现适合存储行的数据结构有两种,即string和hash。

要把Mysql的行数据存入string,首先需要对行数据进行格式化。事实上,结果集的每一行都可以看做若干由字段名和其对应值组成的键值对集合。这种键值对结构很容易让我们想起Json格式。因此,这里选用Json格式作为结果集每一行的格式化模板。根据这一想法,我们可以实现将结果集格式化为若干Json对象,并将Json对象转化为字符串存入Redis的代码:[cpp] view plain copy

// 该函数把结果集中的每一行转换为一个Json格式的字符串并存入Redis的STRING结构中,

// STRING键应该包含结果集标识符和STRING编号,形式如“cache.string:123456:1”

string Cache2String(sql::Connection *mysql_connection,

redisContext *redis_connection,

sql::ResultSet *resultset,

const string &resultset_id, int ttl) {

if (resultset->rowsCount() == 0) {

throw runtime_error("FAILURE - no rows");

}

// STRING键的前缀,包含了结果集的标识符

string prefix("cache.string:" + resultset_id + ":");

unsigned int num_row = 1; // STRING编号,附加于STRING键的末尾,从1开始

sql::ResultSetMetaData *meta = resultset->getMetaData();

unsigned int num_col = meta->getColumnCount();

// 将结果集中所有行对应的所有STRING键存入该SET,SET键包含了结果集的标识符

string redis_row_set_key("resultset.string:" + resultset_id);

redisReply *reply;

string ttlstr;

stringstream ttlstream;

ttlstream <

ttlstr = ttlstream.str();

resultset->beforeFirst();

// 将结果集中的每一行转为Json格式的字符串,将这些Json字符串存入STRING,

// 每个STRING对应结果集中的一行

while (resultset->next()) {

string redis_row_key; // STRING键名,由前缀和STRING编号组成

stringstream keystream;

keystream <

redis_row_key = keystream.str();

Json::Value row;

for (int i = 1; i <= num_col; ++i) {

string col_label = meta->getColumnLabel(i);

string col_value = resultset->getString(col_label);

row[col_label] = col_value;

}

Json::FastWriter writer;

string redis_row_value = writer.write(row);

// 将STRING键及Json格式的对应值对存入Redis

reply = static_cast(redisCommand(redis_connection,

"SET %s %s",

redis_row_key.c_str(),

redis_row_value.c_str()));

freeReplyObject(reply);

// 将STRING键加入SET中

reply = static_cast(redisCommand(redis_connection,

"SADD %s %s",

redis_row_set_key.c_str(),

redis_row_key.c_str()));

freeReplyObject(reply);

// 设置STRING的过期时间

reply = static_cast(redisCommand(redis_connection,

"EXPIRE %s %s",

redis_row_key.c_str(),

ttlstr.c_str()));

freeReplyObject(reply);

++num_row;

}

// 设置SET的过期时间

reply = static_cast(redisCommand(redis_connection,

"EXPIRE %s %s",

redis_row_set_key.c_str(),

ttlstr.c_str()));

freeReplyObject(reply);

return redis_row_set_key; // 返回SET键,以便于其他函数获取该SET中的内容

}

[cpp] view plain copy

// 该函数把结果集中的每一行都存入一个HASH结构。HASH键应当包括结果集标识符和HASH编号,

// 形如“cache.string:123456:1”

string Cache2Hash(sql::Connection *mysql_connection,

redisContext *redis_connection,

sql::ResultSet *resultset,

const string &resultset_id, int ttl) {

if (resultset->rowsCount() == 0) {

throw runtime_error("FAILURE - no rows");

}

// HASH键的前缀,包含了结果集的标识符

string prefix("cache.hash:" + resultset_id + ":");

unsigned int num_row = 1; // HASH编号,附加于HASH键的末尾,从1开始

sql::ResultSetMetaData *meta = resultset->getMetaData();

unsigned int num_col = meta->getColumnCount();

// 将结果集中所有行对应的所有HASH键存入该SET,SET键包含了结果集的标识符

string redis_row_set_key("resultset.hash:" + resultset_id);

redisReply *reply;

string ttlstr;

stringstream ttlstream;

ttlstream <

ttlstr = ttlstream.str();

// 结果集中的每一行对应于一个HASH,将结果集的所有行都存入相应HASH中

resultset->beforeFirst();

while (resultset->next()) {

string redis_row_key; // HASH键名,由前缀和HASH编号组成

stringstream keystream;

keystream <

redis_row_key = keystream.str();

for (int i = 1; i <= num_col; ++i) {

string col_label = meta->getColumnLabel(i);

string col_value = resultset->getString(col_label);

// 将结果集中一行的字段名和对应值存入HASH

reply = static_cast(redisCommand(redis_connection,

"HSET %s %s %s",

redis_row_key.c_str(),

col_label.c_str(),

col_value.c_str()));

freeReplyObject(reply);

}

// 将HASH键加入SET中

reply = static_cast(redisCommand(redis_connection,

"SADD %s %s",

redis_row_set_key.c_str(),

redis_row_key.c_str()));

freeReplyObject(reply);

// 设置HASH的过期时间

reply = static_cast(redisCommand(redis_connection,

"EXPIRE %s %s",

redis_row_key.c_str(),

ttlstr.c_str()));

freeReplyObject(reply);

++num_row;

}

// 设置SET的过期时间

reply = static_cast(redisCommand(redis_connection,

"EXPIRE %s %s",

redis_row_set_key.c_str(),

ttlstr.c_str()));

freeReplyObject(reply);

return redis_row_set_key; // 返回SET键,以便于其他函数获取该SET中的内容

}

至此,我们已经给出了两种存储Mysql结果集的方案,这就是我们在篇首提出的第一个问题,即选择何种数据结构存储Mysql结果集的答案。下一篇文章将研究第二个问题,即数据结构键的标识符选择问题。

本文由职坐标整理并发布,希望对同学们学习MySQL有所帮助,更多内容请关注职坐标数据库MySQL数据库频道!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值