標簽服務實現(xiàn)漫談

標簽服務是一個較為通用的基礎業(yè)務服務,比如博客系統(tǒng)對文章加標簽、社交網(wǎng)絡中為好友添加印象、收藏的歌曲貼標簽方便整理等等。
其主要提供兩類接口:
標簽實體的管理 / 查詢:負責標簽實體的 CRUD
標簽關聯(lián)的管理 / 查詢:將外部業(yè)務實體與標簽建立 / 刪除關聯(lián),根據(jù)外部業(yè)務實體 id 查詢標簽集

RDB 實現(xiàn)
基于關系型數(shù)據(jù)庫的實現(xiàn)是最容易的,并且上大多數(shù)應用也是這樣做的。
建立 tag
表,其中包含了 tag 的基礎屬性,例如 name
、description

建立 tag_rel
關聯(lián)表,其中主要包含了 object_id
、tag_id

管理服務(創(chuàng)建 / 更新 / 刪除)的實現(xiàn)非常容易;根據(jù) object_id
查詢其對應的標簽集也很容易實現(xiàn):
SELECT tag_rel.tag_id, tag_rel.object_id, tag.nameFROM tag_relLEFT JOIN tag ON tag_rel.tag_id = tag.tag_idWHERE tag_rel.object_id = '2db775c1d2174a8c67fc39b86c3fc168'

問題
RDB 實現(xiàn)標簽服務時最主要會面臨的是性能問題,隨著 tag_rel
數(shù)據(jù)量的不斷增長,上面查詢的性能會不斷下降。
優(yōu)化
數(shù)據(jù)庫
給列 tag_rel.object_id
加普通索引
升級數(shù)據(jù)庫服務器硬件配置
使用數(shù)據(jù)庫產(chǎn)品的特性,比如表分區(qū) / 內存表

在應用層面,可以緩存查詢結果,如果實時性要求不高,緩存機制是比較容易實現(xiàn)的,但大多數(shù)業(yè)務場景可能并不適用。
分表
前面提到的數(shù)據(jù)庫產(chǎn)品的表分區(qū)特性(Oracle)我們也可以在應用層代碼通過分表來實現(xiàn)。
建立多張標簽關聯(lián)表 tag_rel_0
、tag_rel_1
、...、tag_rel_31

將查詢條件 object_id
通過某種散列算法(比如 UUID 字符串的話可以通過 FNV Hash 后取模 32)得到 [0, 31] 的結果
SQL 落到具體的某張具體的分表上 FROM tag_rel_16

大部分應用應該通過分表就能解決性能問題,還解決不了的話可以通過這個思路進行分庫、分實例。
NoSQL 實現(xiàn)
基于前文的背景可知,標簽服務的定位是一個獨立的服務,并不維護業(yè)務主體(object),所以將標簽嵌套到業(yè)務主體中的設計在這里并不適合。
排除了這一條,我們還是只能用 RDB 的思想來進行設計:
數(shù)據(jù)結構沿用 RDB 設計,即同樣分為兩個“表”:tag
、tag_rel

將 SQL 中的 join 分成兩步進行:1. 根據(jù) object_id
查詢出 tag_id
集合;2. 根據(jù) tag_id
集合查詢出 tag
集合

Redis
Redis 介紹和“為什么選用 Redis”略過。下面我們介紹一下如何使用 Redis 實現(xiàn)上述思路。
數(shù)據(jù)類型
我們可以使用 Redis Hash
類型來保存標簽,使用 Redis Set
來保存標簽關聯(lián)(這也是 Redis 官方文檔的示例)。
給新聞(id: 1000)添加 4 個標簽(通過 id 關聯(lián)):

sadd news:1000:tags 1 2 5 77(integer) 4

添加反向關聯(lián):

sadd tag:1:news 1000(integer) 1> sadd tag:2:news 1000(integer) 1> sadd tag:5:news 1000(integer) 1> sadd tag:77:news 1000(integer) 1

查詢該新聞的標簽 id 集合:

smembers news:1000:tags1. 52. 13. 774. 2

然后根據(jù)返回的標簽 id 集合查詢標簽。雖然分了兩步進行查詢,但 Redis 的高性能將為我們帶來很低的耗時。
結論
數(shù)據(jù)庫分表能夠解決標簽服務的性能問題實現(xiàn)簡單,在現(xiàn)有實現(xiàn)的基礎上改造很小
依然是基于關系型數(shù)據(jù)庫,不用調整技術架構,開發(fā)模式、運維等保持不變

使用 Redis 同樣可以實現(xiàn)標簽服務使用 Hash 保存標簽、Set 保存關聯(lián)關系
分兩步進行查詢,Redis 自身的實現(xiàn)解決性能問題
原文地址:http://88250.b3log.org/articles/2015/12/01/1448958541321.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • 6 跟蹤用戶動作 在上一章中,你用jQuery實現(xiàn)了AJAX視圖,并構建了一個分享其它網(wǎng)站內容的JavaScrip...
    lakerszhy閱讀 1,303評論 0 1
  • 全文鏈接 第一章 創(chuàng)建一個blog應用第二章 使用高級特性來增強你的blog第三章 擴展你的blog應用第四章上 ...
    夜夜月閱讀 7,135評論 25 27
  • 最美妙的感覺,就是在放學的公車上,占好一個位置,期待下一站你的上車,然后坐在我身旁,盡管我并不知道你會從哪里來,會...
    這玖子閱讀 272評論 0 0
  • ...
    不羈的風FW閱讀 469評論 8 11

友情鏈接更多精彩內容