首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

Redis 與 MySQL 實現標簽系統對比實戰

     編輯:MySQL 綜合教學

Redis 與 MySQL 實現標簽系統對比實戰

標簽系統是內容平台、電商、社交應用的核心功能。關係型數據庫與鍵值存儲在建模、查詢、擴展性上有本質差異。本文通過具體表結構、數據映射、核心查詢對比,揭示兩種方案的優劣與適用場景。

一、MySQL 關係型建模(三表規範化)

-- 內容表
CREATE TABLE `content` (
  `id` INT UNSIGNED NOT NULL PRIMARY KEY,
  `name` VARCHAR(60) DEFAULT NULL,
  `created_timestamp` TIMESTAMP NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 標簽表
CREATE TABLE `tag` (
  `tag_name` VARCHAR(60) NOT NULL PRIMARY KEY,
  `visit_count` INT UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 多對多關聯表
CREATE TABLE `content_tag_relation` (
  `content_id` INT UNSIGNED NOT NULL,
  `tag_name` VARCHAR(60) NOT NULL,
  PRIMARY KEY (`content_id`, `tag_name`),
  FOREIGN KEY (`content_id`) REFERENCES `content`(`id`),
  FOREIGN KEY (`tag_name`) REFERENCES `tag`(`tag_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心查詢

-- 1. 獲取標簽對應的文章名
SELECT c.name 
FROM content c
JOIN content_tag_relation ctr ON c.id = ctr.content_id
WHERE ctr.tag_name = 'mysql';

-- 2. 訪問量Top 3標簽
SELECT tag_name FROM tag ORDER BY visit_count DESC LIMIT 3;

優點:ACID事務、成熟生態、複雜關聯查詢靈活、工具鏈完善。
缺點:多表JOIN性能隨數據量增長下降、寫入需維護三表、水平擴展困難。

二、Redis 多數據結構建模

利用Redis豐富數據類型,針對不同訪問模式優化存儲:

1. 內容存儲:String(JSON) vs Hash

-- String + JSON(簡單、整體讀寫)
SET string:content_id:4 '{"name":"test48601","created_timestamp":"2012-01-01 05:41:01"}'
GET string:content_id:4
-- 缺點:需應用層解析JSON,無法單獨獲取/更新某字段

-- Hash(字段級操作,高效)
HSET hset:content_id:4 name 'test48601'
HSET hset:content_id:4 created_timestamp '2012-01-01 05:41:01'
HGET hset:content_id:4 name           -- 直接獲取單字段
HGETALL hset:content_id:4             -- 獲取所有字段

結論:高頻單字段訪問用Hash,整體讀寫用String+JSON。

2. 標簽訪問統計:有序集合

-- ZADD score=訪問量 member=標簽名
ZADD zset:tag 680 'database'
ZADD zset:tag 469 'db2'

-- 獲取Top 3(按分數降序)
ZREVRANGEBYSCORE zset:tag +inf 0 LIMIT 0 3
-- 返回: mongodb, sql, postgresql

優勢:原生支持排序、分頁、範圍查詢,O(log N + M)極高效。

3. 內容-標簽關係:集合

-- 內容4擁有標簽: role, mongodb, database
SADD set:content_id:4 'role' 'mongodb' 'database'

-- 獲取內容4的所有標簽
SMEMBERS set:content_id:4
-- 返回: database, role, mongodb

優勢:O(1)增刪查、自動去重、支持交並差集運算。

三、複雜查詢對比:獲取標簽對應文章名

MySQL:單條SQL,聲明式

SELECT c.name FROM content c
JOIN content_tag_relation ctr ON c.id = ctr.content_id
WHERE ctr.tag_name = 'mysql';

Redis:需應用層迭代或冗余索引

方案A:應用層掃描(低效、不推薦生產)

# Python偽代碼
content_id_keys = r.keys('set:content_id:*')
for key in content_id_keys:
    if r.sismember(key, 'mysql'):
        content_key = key.replace('set:', 'string:')
        name = json.loads(r.get(content_key))['name']
        print(name)

缺點:KEYS阻塞、全掃描O(N)、應用層邏輯複雜。

方案B:反向冗余索引(推薦)

-- 標簽 -> 內容名/ID 映射集合
SADD tag:mysql 'test123' 'test133' 'test144' 'test155'
SMEMBERS tag:mysql  -- 直接獲取

寫入時雙寫:SADD set:content_id:4 tag 同時 SADD tag:tag content_id。
空間換時間,查詢O(1),完美解決「反向查詢」難題。

四、方案選型決策矩陣

維度MySQLRedis
數據一致性強一致性(ACID)最終一致性(需應用保證雙寫)
查詢靈活性極高(任意JOIN/聚合)低(需預建索引結構)
寫入性能中等(多表、索引維護)極高(O(1)數據結構操作)
讀取性能(熱數據)中等(依賴緩存/索引)極高(內存、專用結構)
存儲成本低(磁盤)高(內存)
擴展性垂直為主、分庫分表複雜原生Cluster水平擴展
運維複雜度成熟、工具豐富需關注持久化、內存、集群運維
適用場景核心業務、異構查詢、強一致要求高併發標簽統計、推薦、緩存、會話

五、最佳實踐:混合架構

生產環境常采用 MySQL為主存儲(權威數據源) + Redis為輔助索引/緩存(高頻查詢加速):

  1. 寫入:先寫MySQL(事務保證三表一致),再異步/同步更新Redis結構
  2. 讀取:
    • 標簽Top N、內容標簽列表 → 直讀Redis
    • 複雜報表、後台管理、全文搜索 → 查MySQL
  3. 數據修復:定期對賬,以MySQL為準重建Redis索引

六、總結

  • MySQL以規範化關係模型保證數據完整性,適合核心業務持久化
  • Redis以針對性數據結構(Hash/Set/ZSet)極致優化讀寫性能,適合高併發查詢加速
  • 反向索引冗余是Redis解決關聯查詢的關鍵模式
  • 架構演進:單體→讀寫分離→分庫分表→引入Redis緩存→混合存儲
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved