99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

redis緩存mysql數(shù)據(jù)

lhl545545 ? 來(lái)源:電子發(fā)燒友網(wǎng) ? 2018-02-09 15:42 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

用Redis作Mysql數(shù)據(jù)庫(kù)緩存,必須解決2個(gè)問(wèn)題。首先,應(yīng)該確定用何種數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)來(lái)自Mysql的數(shù)據(jù);在確定數(shù)據(jù)結(jié)構(gòu)之后,還要考慮用什么標(biāo)識(shí)作為該數(shù)據(jù)結(jié)構(gòu)的鍵。

直觀上看,Mysql中的數(shù)據(jù)都是按表存儲(chǔ)的;更微觀地看,這些表都是按行存儲(chǔ)的。每執(zhí)行一次select查詢,Mysql都會(huì)返回一個(gè)結(jié)果集,這個(gè)結(jié)果集由若干行組成。所以,一個(gè)自然而然的想法就是在Redis中找到一種對(duì)應(yīng)于Mysql行的數(shù)據(jù)結(jié)構(gòu)。Redis中提供了五種基本數(shù)據(jù)結(jié)構(gòu),即字符串(string)、列表(list)、哈希(hash)、集合(set)和有序集合(sorted set)。經(jīng)過(guò)調(diào)研,發(fā)現(xiàn)適合存儲(chǔ)行的數(shù)據(jù)結(jié)構(gòu)有兩種,即string和hash。

要把Mysql的行數(shù)據(jù)存入string,首先需要對(duì)行數(shù)據(jù)進(jìn)行格式化。事實(shí)上,結(jié)果集的每一行都可以看做若干由字段名和其對(duì)應(yīng)值組成的鍵值對(duì)集合。這種鍵值對(duì)結(jié)構(gòu)很容易讓我們想起Json格式。因此,這里選用Json格式作為結(jié)果集每一行的格式化模板。根據(jù)這一想法,我們可以實(shí)現(xiàn)將結(jié)果集格式化為若干Json對(duì)象,并將Json對(duì)象轉(zhuǎn)化為字符串存入Redis的代碼:

view sourceprint?

01.

// 該函數(shù)把結(jié)果集中的每一行轉(zhuǎn)換為一個(gè)Json格式的字符串并存入Redis的STRING結(jié)構(gòu)中,

02.

// STRING鍵應(yīng)該包含結(jié)果集標(biāo)識(shí)符和STRING編號(hào),形式如“cache.string:123456:1”

03.

string Cache2String(sql::Connection *mysql_connection,

04.

redisContext *redis_connection,

05.

sql::ResultSet *resultset,

06.

const string &resultset_id, int ttl) {

07.

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

08.

throw runtime_error(“FAILURE - no rows”);

09.

}

10.

// STRING鍵的前綴,包含了結(jié)果集的標(biāo)識(shí)符

11.

string prefix(“cache.string:” + resultset_id + “:”);

12.

unsigned int num_row = 1; // STRING編號(hào),附加于STRING鍵的末尾,從1開始

13.

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

14.

unsigned int num_col = meta->getColumnCount();

15.

// 將結(jié)果集中所有行對(duì)應(yīng)的所有STRING鍵存入該SET,SET鍵包含了結(jié)果集的標(biāo)識(shí)符

16.

string redis_row_set_key(“resultset.string:” + resultset_id);

17.

redisReply *reply;

18.

string ttlstr;

19.

stringstream ttlstream;

20.

ttlstream << ttl;

21.

ttlstr = ttlstream.str();

22.

resultset->beforeFirst();

23.

// 將結(jié)果集中的每一行轉(zhuǎn)為Json格式的字符串,將這些Json字符串存入STRING,

24.

// 每個(gè)STRING對(duì)應(yīng)結(jié)果集中的一行

25.

while (resultset->next()) {

26.

string redis_row_key; // STRING鍵名,由前綴和STRING編號(hào)組成

27.

stringstream keystream;

28.

keystream <

29.

redis_row_key = keystream.str();

30.

Json::Value row;

31.

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

32.

string col_label = meta->getColumnLabel(i);

33.

string col_value = resultset->getString(col_label);

34.

row[col_label] = col_value;

35.

}

36.

Json::FastWriter writer;

37.

string redis_row_value = writer.write(row);

38.

// 將STRING鍵及Json格式的對(duì)應(yīng)值對(duì)存入Redis

39.

reply = static_cast(redisCommand(redis_connection,

40.

“SET %s %s”,

41.

redis_row_key.c_str(),

42.

redis_row_value.c_str()));

43.

freeReplyObject(reply);

44.

// 將STRING鍵加入SET中

45.

reply = static_cast(redisCommand(redis_connection,

46.

“SADD %s %s”,

47.

redis_row_set_key.c_str(),

48.

redis_row_key.c_str()));

49.

freeReplyObject(reply);

50.

// 設(shè)置STRING的過(guò)期時(shí)間

51.

reply = static_cast(redisCommand(redis_connection,

52.

“EXPIRE %s %s”,

53.

redis_row_key.c_str(),

54.

ttlstr.c_str()));

55.

freeReplyObject(reply);

56.

++num_row;

57.

}

58.

// 設(shè)置SET的過(guò)期時(shí)間

59.

reply = static_cast(redisCommand(redis_connection,

60.

“EXPIRE %s %s”,

61.

redis_row_set_key.c_str(),

62.

ttlstr.c_str()));

63.

freeReplyObject(reply);

64.

return redis_row_set_key; // 返回SET鍵,以便于其他函數(shù)獲取該SET中的內(nèi)容

65.

}

要把Mysql的行數(shù)據(jù)存入hash,過(guò)程要比把數(shù)據(jù)存入string直觀很多。這是由hash的結(jié)構(gòu)性質(zhì)決定的——hash本身就是一個(gè)鍵值對(duì)集合:一個(gè)“父鍵”下面包含了很多“子鍵”,每個(gè)“子鍵”都對(duì)應(yīng)一個(gè)值。根據(jù)前面的分析可知,結(jié)果集中的每一行實(shí)際上也是鍵值對(duì)集合。用Redis鍵值對(duì)集合表示Mysql鍵值對(duì)集合應(yīng)該再合適不過(guò)了:對(duì)于結(jié)果集中的某一行,字段對(duì)應(yīng)于hash的“子鍵”,字段對(duì)應(yīng)的值就是hash“子鍵”對(duì)應(yīng)的值,即結(jié)果集的一行剛好對(duì)應(yīng)一個(gè)hash。這一想法的實(shí)現(xiàn)代碼如下:

view sourceprint?

01.

// 該函數(shù)把結(jié)果集中的每一行都存入一個(gè)HASH結(jié)構(gòu)。HASH鍵應(yīng)當(dāng)包括結(jié)果集標(biāo)識(shí)符和HASH編號(hào),

02.

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

03.

string Cache2Hash(sql::Connection *mysql_connection,

04.

redisContext *redis_connection,

05.

sql::ResultSet *resultset,

06.

const string &resultset_id, int ttl) {

07.

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

08.

throw runtime_error(“FAILURE - no rows”);

09.

}

10.

// HASH鍵的前綴,包含了結(jié)果集的標(biāo)識(shí)符

11.

string prefix(“cache.hash:” + resultset_id + “:”);

12.

unsigned int num_row = 1; // HASH編號(hào),附加于HASH鍵的末尾,從1開始

13.

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

14.

unsigned int num_col = meta->getColumnCount();

15.

// 將結(jié)果集中所有行對(duì)應(yīng)的所有HASH鍵存入該SET,SET鍵包含了結(jié)果集的標(biāo)識(shí)符

16.

string redis_row_set_key(“resultset.hash:” + resultset_id);

17.

redisReply *reply;

18.

string ttlstr;

19.

stringstream ttlstream;

20.

ttlstream << ttl;

21.

ttlstr = ttlstream.str();

22.

// 結(jié)果集中的每一行對(duì)應(yīng)于一個(gè)HASH,將結(jié)果集的所有行都存入相應(yīng)HASH中

23.

resultset->beforeFirst();

24.

while (resultset->next()) {

25.

string redis_row_key; // HASH鍵名,由前綴和HASH編號(hào)組成

26.

stringstream keystream;

27.

keystream << prefix << num_row;

28.

redis_row_key = keystream.str();

29.

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

30.

string col_label = meta->getColumnLabel(i);

31.

string col_value = resultset->getString(col_label);

32.

// 將結(jié)果集中一行的字段名和對(duì)應(yīng)值存入HASH

33.

reply = static_cast(redisCommand(redis_connection,

34.

“HSET %s %s %s”,

35.

redis_row_key.c_str(),

36.

col_label.c_str(),

37.

col_value.c_str()));

38.

freeReplyObject(reply);

39.

}

40.

// 將HASH鍵加入SET中

41.

reply = static_cast(redisCommand(redis_connection,

42.

“SADD %s %s”,

43.

redis_row_set_key.c_str(),

44.

redis_row_key.c_str()));

45.

freeReplyObject(reply);

46.

// 設(shè)置HASH的過(guò)期時(shí)間

47.

reply = static_cast(redisCommand(redis_connection,

48.

“EXPIRE %s %s”,

49.

redis_row_key.c_str(),

50.

ttlstr.c_str()));

51.

freeReplyObject(reply);

52.

++num_row;

53.

}

54.

// 設(shè)置SET的過(guò)期時(shí)間

55.

reply = static_cast(redisCommand(redis_connection,

56.

“EXPIRE %s %s”,

57.

redis_row_set_key.c_str(),

58.

ttlstr.c_str()));

59.

freeReplyObject(reply);

60.

return redis_row_set_key; // 返回SET鍵,以便于其他函數(shù)獲取該SET中的內(nèi)容

61.

}

至此,我們已經(jīng)給出了兩種存儲(chǔ)Mysql結(jié)果集的方案,這就是我們?cè)谄滋岢龅牡谝粋€(gè)問(wèn)題,即選擇何種數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)Mysql結(jié)果集的答案。

把Mysql結(jié)果集緩存到Redis的字符串或哈希結(jié)構(gòu)中以后,我們面臨一個(gè)新的問(wèn)題,即如何為這些字符串或哈希命名,也就是如何確定它們的鍵。因?yàn)檫@些數(shù)據(jù)結(jié)構(gòu)所對(duì)應(yīng)的行都屬于某個(gè)結(jié)果集,假如可以找到一種唯一標(biāo)識(shí)結(jié)果集的方法,那么只需為這些數(shù)據(jù)結(jié)構(gòu)分配一個(gè)唯一的序號(hào),然后把結(jié)果集標(biāo)識(shí)符與該序號(hào)結(jié)合起來(lái),就能唯一標(biāo)識(shí)一個(gè)數(shù)據(jù)結(jié)構(gòu)了。于是,為字符串和哈希命名的問(wèn)題就轉(zhuǎn)化為確定結(jié)果集標(biāo)識(shí)符的問(wèn)題。

經(jīng)過(guò)調(diào)研,發(fā)現(xiàn)一種較為通用的確定結(jié)果集標(biāo)識(shí)符的方法。正如我們所知道的,緩存在Redis中的結(jié)果集數(shù)據(jù)都是利用select等sql語(yǔ)句從Mysql中獲取的。同樣的查詢語(yǔ)句會(huì)生成同樣的結(jié)果集(這里暫時(shí)不討論結(jié)果集中每條記錄的順序問(wèn)題),這一性質(zhì)剛好可以用來(lái)確定結(jié)果集的唯一標(biāo)識(shí)符。當(dāng)然,簡(jiǎn)單地把整個(gè)sql語(yǔ)句作為結(jié)果集標(biāo)識(shí)符是不可取的,一個(gè)顯而易見的理由是,未經(jīng)處理的sql查詢語(yǔ)句均包含若干空格,而Redis的鍵是不允許存在空格的。這時(shí),我們需要一個(gè)可以把sql語(yǔ)句轉(zhuǎn)換為唯一標(biāo)識(shí)符的函數(shù)。通常,這一功能由散列函數(shù)完成,包括MD5,SHA系列等加密散列函數(shù)在內(nèi)的很多算法均可達(dá)到這一目的。

確定結(jié)果集標(biāo)識(shí)符之后,從Redis讀數(shù)據(jù)或向Redis寫數(shù)據(jù)的思路就很清晰了。對(duì)于一個(gè)sql語(yǔ)句格式的數(shù)據(jù)請(qǐng)求,首先計(jì)算該語(yǔ)句的MD5并據(jù)此得到結(jié)果集標(biāo)識(shí)符,然后利用該標(biāo)識(shí)符在Redis中查找該結(jié)果集。注意,結(jié)果集中的每一行都有一個(gè)相應(yīng)的鍵,這些鍵都存儲(chǔ)在一個(gè)Redis集合結(jié)構(gòu)中。這個(gè)集合恰好對(duì)應(yīng)了所需的結(jié)果集,所以,該集合的鍵必須包含結(jié)果集標(biāo)識(shí)符。如果Redis中不存在這樣一個(gè)集合,說(shuō)明要找的結(jié)果集不在Redis中,所以需要執(zhí)行相應(yīng)的sql語(yǔ)句,在Mysql中查詢到相應(yīng)的結(jié)果集,然后按照上面所說(shuō)的辦法把結(jié)果集中的每一行以字符串或哈希的形式存入Redis。在Redis中查找相應(yīng)結(jié)果集的代碼如下:

view sourceprint?

01.

// 該函數(shù)根據(jù)sql語(yǔ)句在Redis中查詢相應(yīng)的結(jié)果集,并返回結(jié)果集中每一行所對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)的鍵

02.

vector GetCache(sql::Connection *mysql_connection,

03.

redisContext *redis_connection,

04.

const string &sql, int ttl, int type) {

05.

vector redis_row_key_vector;

06.

string resultset_id = md5(sql); // 計(jì)算sql語(yǔ)句的md5,這是唯一標(biāo)識(shí)結(jié)果集的關(guān)鍵

07.

// type==1時(shí),該函數(shù)將查詢相應(yīng)的STRING集合或?qū)⒔Y(jié)果集寫入若干STRING

08.

string cache_type = (type == 1) ? “string” : “hash”;

09.

// 根據(jù)type信息和結(jié)果集標(biāo)識(shí)符合成SET鍵

10.

string redis_row_set_key = “resultset.” + cache_type + “:” + resultset_id;

11.

redisReply *reply;

12.

// 嘗試從reply中獲取SET中保存的所有鍵

13.

reply = static_cast(redisCommand(redis_connection,

14.

“SMEMBERS %s”,

15.

redis_row_set_key.c_str()));

16.

if (reply->type == REDIS_REPLY_ARRAY) {

17.

// 如果要找的SET不存在,說(shuō)明Redis中沒有相應(yīng)的結(jié)果集,需要調(diào)用Cache2String或

18.

// Cache2Hash函數(shù)把數(shù)據(jù)從Mysql拉取到Redis中

19.

if (reply->elements == 0) {

20.

freeReplyObject(reply);

21.

sql::Statement *stmt = mysql_connection->createStatement();

22.

sql::ResultSet *resultset = stmt->executeQuery(sql);

23.

if (type == 1) {

24.

redis_row_set_key = Cache2String(mysql_connection, redis_connection,

25.

resultset, resultset_id, ttl);

26.

} else {

27.

redis_row_set_key = Cache2Hash(mysql_connection, redis_connection,

28.

resultset, resultset_id, ttl);

29.

}

30.

// 再次嘗試從reply中獲取SET中保存的所有鍵

31.

reply = static_cast(redisCommand(redis_connection,

32.

“SMEMBERS %s”,

33.

redis_row_set_key.c_str()));

34.

delete resultset;

35.

delete stmt;

36.

}

37.

// 把SET中的每個(gè)STRING或HASH鍵存入redis_row_key_vector中

38.

string redis_row_key;

39.

for (int i = 0; i < reply->elements; ++i) {

40.

redis_row_key = reply->element[i]->str;

41.

redis_row_key_vector.push_back(redis_row_key);

42.

}

43.

freeReplyObject(reply);

44.

} else {

45.

freeReplyObject(reply);

46.

throw runtime_error(“FAILURE - SMEMBERS error”);

47.

}

48.

return redis_row_key_vector;

49.

}

現(xiàn)在我們已經(jīng)掌握了確定Redis中的結(jié)果集標(biāo)識(shí)符以及各數(shù)據(jù)結(jié)構(gòu)的鍵的方法。下一篇文章將研究結(jié)果集在Redis中的排序和分頁(yè)問(wèn)題。

在實(shí)現(xiàn)緩存排序功能之前,必須先明白這一功能的合理性。不妨思考一下,既然可以在數(shù)據(jù)庫(kù)中排序,為什么還要把排序功能放在緩存中實(shí)現(xiàn)呢?這里簡(jiǎn)單總結(jié)了兩個(gè)原因:首先,排序會(huì)增加數(shù)據(jù)庫(kù)的負(fù)載,難以支撐高并發(fā)的應(yīng)用;其次,在緩存中排序不會(huì)遇到表鎖定的問(wèn)題。Redis恰好提供了排序功能,使我們可以方便地實(shí)現(xiàn)緩存排序。

Redis中用于實(shí)現(xiàn)排序功能的是SORT命令。該命令提供了多種參數(shù),可以對(duì)列表,集合和有序集合進(jìn)行排序。SORT命令格式如下:

view sourceprint?

1.

SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern 。..]] [ASC | DESC] [ALPHA] [STORE destination]

BY參數(shù)用于指定排序字段,功能類似于SQL中的order by。對(duì)于列表和集合而言,僅按照它們的值進(jìn)行排序往往沒有實(shí)際意義。以函數(shù)Cache2Hash返回的集合為例(實(shí)際上返回的是集合鍵),該集合中存儲(chǔ)的是一系列完整的哈希鍵,只按照這些鍵進(jìn)行排序,結(jié)果無(wú)非是按照數(shù)字或字典順序排列,其用處顯然不大。這是因?yàn)檎嬲鎯?chǔ)行數(shù)據(jù)的是哈希結(jié)構(gòu)本身,而非哈希鍵。假設(shè)集合鍵為“resultset.hash:123456”,集合中每個(gè)哈希鍵對(duì)應(yīng)的哈希結(jié)構(gòu)中都有一個(gè)名為“timestamp”的字段,現(xiàn)在要把集合中的所有哈希鍵按照timestamp字段進(jìn)行排序,這時(shí),只需執(zhí)行以下命令:

view sourceprint?

1.

SORT resultset.hash:123456 BY *->timestamp

從上例可以看出,BY的真正威力在于它可以讓SORT命令按照一個(gè)指定的外部鍵的外部字段進(jìn)行排序。SORT用集合resultset.hash:123456中的每個(gè)值(即每個(gè)哈希鍵)替換BY參數(shù)后的第一個(gè)“*”,并依據(jù)“->”后面給出的字段獲取其值,最后根據(jù)這些字段值對(duì)哈希鍵進(jìn)行排序。

LIMIT參數(shù)用于限制排序以后返回元素的數(shù)量,功能類似于SQL中的limit。該參數(shù)接受另外兩個(gè)參數(shù),即offset和count,LIMIT offset count表示跳過(guò)前offset個(gè)元素,返回之后的連續(xù)count個(gè)元素。可見,LIMIT參數(shù)可以用于實(shí)現(xiàn)分頁(yè)功能。

GET參數(shù)用于返回指定的字段值。以集合resultset.hash:123456為例,使用BY參數(shù)對(duì)集合中的所有哈希鍵按照哈希結(jié)構(gòu)中的timestamp字段排序后,SORT命令返回所有排序之后的哈希鍵。如果某個(gè)請(qǐng)求需要不是鍵而是某些字段值,這時(shí)就要使用GET參數(shù),使SORT命令返回指定字段值。假設(shè)除timestamp字段以外,集合中每個(gè)哈希鍵對(duì)應(yīng)的哈希結(jié)構(gòu)中還有一個(gè)名為“id”的字段,通過(guò)以下命令可以使SORT返回按照timestamp排序以后的每個(gè)哈希鍵對(duì)應(yīng)的哈希結(jié)構(gòu)中的timestamp和id值:

view sourceprint?

1.

SORT resultset.hash:123456 BY *->timestamp GET *->timestamp GET *->id

SORT用集合resultset.hash:123456中的每個(gè)值(即每個(gè)哈希鍵)替換GET參數(shù)之后的第一個(gè)“*”,并將其作為返回值。值得注意的是,利用GET #能夠得到集合中的哈希鍵本身。

ASC和DESC參數(shù)用于指定排序順序(默認(rèn)為ASC,即從低到高),ALPHA參數(shù)用于按照字典順序排列非數(shù)字元素。

STORE參數(shù)用于將SORT命令的返回值,即排序結(jié)果存入一個(gè)指定的列表。加上STORE參數(shù)后,SORT命令的返回值就變?yōu)榕判蚪Y(jié)果的個(gè)數(shù)。

下面的代碼實(shí)現(xiàn)了按照哈希的某個(gè)字段對(duì)集合中的哈希鍵排序,并將結(jié)果存入列表的過(guò)程:

view sourceprint?

01.

// 該函數(shù)對(duì)集合中的所有HASH鍵進(jìn)行排序,排序依據(jù)是HASH鍵所對(duì)應(yīng)的HASH中的某個(gè)字段,

02.

// 排序結(jié)果被存入一個(gè)LIST結(jié)構(gòu),LIST鍵應(yīng)當(dāng)包含結(jié)果集標(biāo)識(shí)符和排序字段標(biāo)識(shí)符,

03.

// 形如“sorted:123456:1234”

04.

string SortHash(sql::Connection *mysql_connection,

05.

redisContext *redis_connection,

06.

const string &resultset_id,

07.

const string &sort_field,

08.

int offset, int count, int order, int ttl) {

09.

// 只考慮存儲(chǔ)HASH鍵的SET

10.

string redis_row_set_key = “resultset.hash:” + resultset_id;

11.

redisReply *reply;

12.

// 檢測(cè)SET是否存在

13.

reply = static_cast(redisCommand(redis_connection,

14.

“EXISTS %s”,

15.

redis_row_set_key.c_str()));

16.

if (reply->integer == 0) {

17.

freeReplyObject(reply);

18.

throw runtime_error(“FAILURE - no resultsets”);

19.

} else {

20.

freeReplyObject(reply);

21.

}

22.

string field_md5 = md5(sort_field); // 利用MD5排除排序字段中空格造成的影響

23.

// 將排序結(jié)果存入該LIST

24.

string redis_sorted_list_key = “sorted:” + resultset_id + “:” + field_md5;

25.

string by(“*->” + sort_field); //確定排序字段

26.

string ord = (order == 1) ? “ASC” : “DESC”; //order==1時(shí)按照升序排列;否則為降序

27.

stringstream ofsstream, cntstream;

28.

ofsstream << offset;

29.

cntstream << count;

30.

// 執(zhí)行排序命令,并把排序結(jié)果存入LIST

31.

reply = static_cast(redisCommand(

32.

redis_connection,

33.

“SORT %s BY %s LIMIT %s %s GET %s ALPHA STORE %s”,

34.

redis_row_set_key.c_str(),

35.

by.c_str(),

36.

ofsstream.str().c_str(),

37.

cntstream.str().c_str(),

38.

“#”,

39.

redis_sorted_list_key.c_str()));

40.

freeReplyObject(reply);

41.

stringstream ttlstream;

42.

ttlstream << ttl;

43.

// 設(shè)置LIST的過(guò)期時(shí)間

44.

reply = static_cast(redisCommand(redis_connection,

45.

“EXPIRE %s %s”,

46.

redis_sorted_list_key.c_str(),

47.

ttlstream.str().c_str()));

48.

freeReplyObject(reply);

49.

return redis_sorted_list_key; // 返回LIST鍵,以便于其他函數(shù)獲取該LIST中的內(nèi)容

顯然,對(duì)結(jié)果集中的哈希鍵進(jìn)行排序要比對(duì)字符串鍵排序更加直觀和方便。借助于排序函數(shù),可以方便地實(shí)現(xiàn)在Redis中查詢排序后的結(jié)果集,代碼如下:

view sourceprint?

01.

// 該函數(shù)根據(jù)sql語(yǔ)句和排序參數(shù),在Redis中查詢相應(yīng)的結(jié)果集并進(jìn)行排序,最后返回

02.

// 排序之后的HASH鍵

03.

vector GetSortedCache(sql::Connection *mysql_connection,

04.

redisContext *redis_connection,

05.

const string &sql, const string &sort_field,

06.

int offset, int count, int order, int ttl) {

07.

vector redis_row_key_vector;

08.

redisReply *reply;

09.

string resultset_id = md5(sql); // 結(jié)果集標(biāo)識(shí)符

10.

string field_md5 = md5(sort_field); // 排序字段標(biāo)識(shí)符

11.

// 嘗試獲取LIST中的所有HASH鍵

12.

string redis_sorted_list_key = “sorted:” + resultset_id + “:” + field_md5;

13.

// 嘗試獲取LIST中的所有HASH鍵

14.

reply = static_cast(redisCommand(redis_connection,

15.

“LRANGE %s %s %s”,

16.

redis_sorted_list_key.c_str(),

17.

“0”,

18.

“-1”));

19.

if (reply->type == REDIS_REPLY_ARRAY) {

20.

// 如果LIST不存在,調(diào)用Cache2Hash函數(shù)從Mysql中拉取數(shù)據(jù)到Redis,然后調(diào)用SortHash函數(shù)

21.

// 對(duì)結(jié)果集進(jìn)行排序并將排序后的HASH鍵存入LIST

22.

if (reply->elements == 0) {

23.

freeReplyObject(reply);

24.

sql::Statement *stmt = mysql_connection->createStatement();

25.

sql::ResultSet *resultset = stmt->executeQuery(sql);

26.

Cache2Hash(mysql_connection, redis_connection, resultset,

27.

resultset_id, ttl);

28.

redis_sorted_list_key = SortHash(mysql_connection, redis_connection,

29.

resultset_id, sort_field, offset,

30.

count, order, ttl);

31.

// 再次嘗試獲取LIST中的所有HASH鍵

32.

reply = static_cast(redisCommand(

33.

redis_connection,

34.

“LRANGE %s %s %s”,

35.

redis_sorted_list_key.c_str(),

36.

“0”,

37.

“-1”));

38.

delete resultset;

39.

delete stmt;

40.

}

41.

// 將LIST中的所有HASH鍵存入redis_row_key_vector中

42.

string redis_row_key;

43.

for (int i = 0; i < reply->elements; ++i) {

44.

redis_row_key = reply->element[i]->str;

45.

redis_row_key_vector.push_back(redis_row_key);

46.

}

47.

freeReplyObject(reply);

48.

} else {

49.

freeReplyObject(reply);

50.

throw runtime_error(“FAILURE - LRANGE error”);

51.

}

52.

return redis_row_key_vector;

53.

}

這樣,在Redis中對(duì)結(jié)果集進(jìn)行簡(jiǎn)單排序操作的功能就實(shí)現(xiàn)了。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    860

    瀏覽量

    27955
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    387

    瀏覽量

    11454
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    MySQL數(shù)據(jù)備份與恢復(fù)策略

    數(shù)據(jù)是企業(yè)的核心資產(chǎn),MySQL作為主流的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),其數(shù)據(jù)的安全性和可靠性至關(guān)重要。本文將深入探討MySQL
    的頭像 發(fā)表于 07-14 11:11 ?137次閱讀

    【幸狐Omni3576邊緣計(jì)算套件試用體驗(yàn)】Redis最新8.0.2版本源碼安裝及性能測(cè)試

    engine, and message broker. 數(shù)以百萬(wàn)計(jì)的開發(fā)人員用作數(shù)據(jù)庫(kù)、緩存、流式處理引擎和消息代理的開源內(nèi)存數(shù)據(jù)存儲(chǔ)。 二、源碼編譯Redis 2.1 安裝git
    發(fā)表于 06-03 01:28

    MySQL數(shù)據(jù)庫(kù)是什么

    MySQL數(shù)據(jù)庫(kù)是一種 開源的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS) ,由瑞典MySQL AB公司開發(fā),后被Oracle公司收購(gòu)。它通過(guò)結(jié)構(gòu)化查詢語(yǔ)言(SQL)進(jìn)行
    的頭像 發(fā)表于 05-23 09:18 ?456次閱讀

    HarmonyOS5云服務(wù)技術(shù)分享--云緩存快速上手指南

    維煩惱,非常適合高并發(fā)場(chǎng)景下的數(shù)據(jù)快速讀寫需求 下面我將從信息獲取到代碼實(shí)戰(zhàn),手把手帶大家實(shí)現(xiàn)云緩存接入。 一、云緩存信息獲取全攻略 1.1 基礎(chǔ)信息獲取 ??登錄控制臺(tái)?? 打開AppGallery
    發(fā)表于 05-22 18:37

    利用dockerfile搭建mysql主從集群和redis集群

    ==MySQL主從同步(Replication)是一種實(shí)現(xiàn)數(shù)據(jù)冗余和高可用性的技術(shù),通過(guò)將主數(shù)據(jù)庫(kù)(Master)的變更操作同步到一個(gè)或多個(gè)從數(shù)據(jù)庫(kù)(Slave),實(shí)現(xiàn)
    的頭像 發(fā)表于 05-14 11:38 ?406次閱讀
    利用dockerfile搭建<b class='flag-5'>mysql</b>主從集群和<b class='flag-5'>redis</b>集群

    Redis實(shí)戰(zhàn)筆記

    在目前的技術(shù)選型中,Redis 儼然已經(jīng)成為了系統(tǒng)高性能緩存方案的事實(shí)標(biāo)準(zhǔn),因此現(xiàn)在?Redis 也成為了后端開發(fā)的基本技能樹之一。 ? 基于上述情況,今天給大家分享一份?杰哥?親筆撰寫的內(nèi)部
    的頭像 發(fā)表于 02-09 09:12 ?399次閱讀
    <b class='flag-5'>Redis</b>實(shí)戰(zhàn)筆記

    Redis Cluster之故障轉(zhuǎn)移

    1. Redis Cluster 簡(jiǎn)介 Redis Cluster 是 Redis 官方提供的 Redis 集群功能。 為什么要實(shí)現(xiàn) Redis
    的頭像 發(fā)表于 01-20 09:21 ?896次閱讀
    <b class='flag-5'>Redis</b> Cluster之故障轉(zhuǎn)移

    適用于MySQL和MariaDB的Python連接器:可靠的MySQL數(shù)據(jù)連接器和數(shù)據(jù)庫(kù)

    和 Linux 的 wheel 包分發(fā)。 直接連接 該解決方案使您能夠通過(guò) TCP/IP 建立與 MySQL 或者 MariaDB 數(shù)據(jù)庫(kù)服務(wù)器的直接連接,而無(wú)需數(shù)據(jù)庫(kù)客戶端庫(kù)。另外直接連接可以提高 Python 應(yīng)用程
    的頭像 發(fā)表于 01-17 12:18 ?501次閱讀
    適用于<b class='flag-5'>MySQL</b>和MariaDB的Python連接器:可靠的<b class='flag-5'>MySQL</b><b class='flag-5'>數(shù)據(jù)</b>連接器和<b class='flag-5'>數(shù)據(jù)</b>庫(kù)

    基于javaPoet的緩存key優(yōu)化實(shí)踐

    數(shù)據(jù)庫(kù)中的熱數(shù)據(jù)緩存redis/本地緩存中,代碼如下: ? @Cacheable(value = { "per" }, key="#per
    的頭像 發(fā)表于 01-14 15:18 ?826次閱讀
    基于javaPoet的<b class='flag-5'>緩存</b>key優(yōu)化實(shí)踐

    MySQL數(shù)據(jù)庫(kù)的安裝

    MySQL數(shù)據(jù)庫(kù)的安裝 【一】各種數(shù)據(jù)庫(kù)的端口 MySQL :3306 Redis :6379 MongoDB :27017 Django
    的頭像 發(fā)表于 01-14 11:25 ?567次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>數(shù)據(jù)</b>庫(kù)的安裝

    云服務(wù)器 Flexus X 實(shí)例 MySQL 應(yīng)用加速測(cè)試

    文章目錄 目錄 文章目錄 ? 購(gòu)買配置 ? 基本配置參考如下: ? 連接服務(wù)器 ? 查詢MySQL狀態(tài) ? 啟動(dòng)MySQL ? 添加配置 ? 添加密碼并修改權(quán)限 ? 性能測(cè)試 ? C#插入數(shù)據(jù)
    的頭像 發(fā)表于 12-24 12:19 ?519次閱讀
    云服務(wù)器 Flexus X 實(shí)例 <b class='flag-5'>MySQL</b> 應(yīng)用加速測(cè)試

    緩存對(duì)大數(shù)據(jù)處理的影響分析

    緩存對(duì)大數(shù)據(jù)處理的影響顯著且重要,主要體現(xiàn)在以下幾個(gè)方面: 一、提高數(shù)據(jù)訪問(wèn)速度 在大數(shù)據(jù)環(huán)境中,數(shù)據(jù)存儲(chǔ)通常采用分布式存儲(chǔ)系統(tǒng),
    的頭像 發(fā)表于 12-18 09:45 ?779次閱讀

    Redis緩存與Memcached的比較

    Redis和Memcached都是廣泛使用的內(nèi)存數(shù)據(jù)存儲(chǔ)系統(tǒng),它們主要用于提高應(yīng)用程序的性能,通過(guò)減少對(duì)數(shù)據(jù)庫(kù)的直接訪問(wèn)來(lái)加速數(shù)據(jù)檢索。以下是對(duì)Re
    的頭像 發(fā)表于 12-18 09:33 ?598次閱讀

    數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)—Mysql數(shù)據(jù)庫(kù)表記錄丟失的數(shù)據(jù)恢復(fù)流程

    Mysql數(shù)據(jù)庫(kù)故障: Mysql數(shù)據(jù)庫(kù)表記錄丟失。 Mysql數(shù)據(jù)庫(kù)故障表現(xiàn): 1、
    的頭像 發(fā)表于 12-16 11:05 ?618次閱讀
    <b class='flag-5'>數(shù)據(jù)</b>庫(kù)<b class='flag-5'>數(shù)據(jù)</b>恢復(fù)—<b class='flag-5'>Mysql</b><b class='flag-5'>數(shù)據(jù)</b>庫(kù)表記錄丟失的<b class='flag-5'>數(shù)據(jù)</b>恢復(fù)流程

    聊聊緩存擊穿的解決方法

    緩存擊穿,Redis中的某個(gè)熱點(diǎn)key不存在或者過(guò)期,但是此時(shí)有大量的用戶訪問(wèn)該key。比如xxx直播間優(yōu)惠券搶購(gòu)、xxx商品活動(dòng),這時(shí)候大量用戶會(huì)在某個(gè)時(shí)間點(diǎn)一同訪問(wèn)該熱點(diǎn)事件。但是可能
    的頭像 發(fā)表于 10-23 13:54 ?536次閱讀