1. 程式人生 > >站內訊息設計與實現

站內訊息設計與實現

0x01.About

最近在處理系統訊息模組,查閱了很多實踐案例,各有針對性。

首先站內訊息主要包括:個人訊息(評論,點贊),系統訊息,訂閱訊息,私信。

其中,訂閱區分使用者群,即系統訊息是一個特殊的所有人訂閱的訂閱訊息,特點是一對多。

前三個實時性比較低,最後一個實時性高,離線狀態下是私信,如果雙方線上要轉為聊天室,特點是一對一。

那麼,接下來,該選個方案了,SQL or NoSQL?

0x02.Mysql實現

首先,對於個人訊息、私信("UserMessage"),一條訊息插一句,Mysql跑跑沒問題。

對於系統訊息或訂閱訊息,必然不可以,假如有10萬用戶,一次性那麼要插入10萬條訊息,Mysql必死。

那麼就是說,要設立一個系統庫("SystemMessage"),每當使用者登入,就去跑跑系統庫("SystemMessage"),把未讀的系統庫跑到個人庫。

關於訂閱訊息就比較麻煩了,對使用者分組?對訊息分組?

關係型資料庫處理集合問題是比較麻煩的,目前想到的結論是建立一個表("RssMessage")儲存訊息型別,訊息索引。

下面列了大致的資料庫模型:

看完這個資料庫設計,我也覺得好難受,吐槽前先來想想為什麼吧。

UserSystemRelation表用於記錄使用者讀取到哪個位置的標記。

可以看到,UserMessage與SystemMessage表中,title、tid、ctime、type欄位冗餘了,好像也沒必要,

但是從使用者功能上看,當用戶登陸後,查詢自己站內訊息,必然要用到的有:status,必然要顯示的有:title、ctime,type作為使用者進入訊息面板後,要篩選的方式之一,這樣的話,Mysql就只要跑一個表就可以完成顯示給使用者的最新站內訊息了。

由於MessageText可能是一個大資訊通知,使用者檢視個人訊息時候,並未檢視MessageText內容,所以單獨放一張表。

相應處理流程

  • 使用者登入後,先通過"UserSystemRelation"表查詢是否有新的系統訊息
  • 如果"UserSystemRelation",查詢到自身uid,同步系統訊息到個人訊息;如果"UserSystemRelation"未查詢到自身uid,直接插入"UserSystemRelation",並讀取最近50條系統訊息。
  • 使用者點選未讀訊息,獲取"MessageText"",並更新狀態(status)為已讀。
  • 使用者通過"status"、"type",可以篩選系統訊息。

0x03.Mysql+MongoDB實現

由於Mongodb是一種文件型的資料結構,所以,可以考慮把所有資料轉成json直接塞給Mongodb。

基於使用者的習慣,讀多寫少,大部分時候都是看到訊息,刪除、更新比較少,如果資料沒更新直接讀Mongodb,如果資料更新,直接刪除Mongodb的索引。

這個考慮是在,使用者數量很大的時候,要在"UserSystem"表裡查詢到使用者訊息比較慢的時候用,類似於吧Mongodb當快取。

0x04.Redis實現

看了Mysql下站內訊息的資料庫設計,我也覺得很蛋疼,臨時過渡沒事,但是還是NoSQL合適。

在下圖展示的這個 pubsub_channels 示例中, client2 、 client5 和 client1 就訂閱了 channel1 , 而其他頻道也分別被別的客戶端所訂閱:

只要是訂閱了相應地頻道,就會收到頻道的訊息。

把使用者ID作為頻道,私信就是反向的頻道訂閱,系統訊息就是所有使用者的訂閱,那麼離線的訊息呢?

1、線上使用者

還是存在系統或個人的雜湊表裡,等上線後再去讀取。

在Python中,訂閱釋出訊息(Publish)如下:

import redis,time
queue = redis.StrictRedis(host='localhost', port=6379, db=0)
channel = queue.pubsub()

for i in range(100): 
    queue.publish("test", i)
    time.sleep(0.1)

Python中,訂閱監聽訊息(Subcribe)如下:

import redis,time
r = redis.StrictRedis(host='localhost', port=6379, db=0)
p = r.pubsub()
p.subscribe('test')

while True:
    message = p.get_message()
    if message:
        print "Subscriber: %s" % message['data']

這是線上使用者做法。

2、線下使用者

看過一種做法是建立一個Redis連結串列,儲存登陸使用者,當用戶登陸就直接傳送,沒登陸就暫存起來。

這裡的話,可以用WebSocket實時監聽,定期傳送心跳包,如果線上直接返回Redis自帶的訂閱系統。

系統訊息建立一個集合:

SADD system:2015-08-03 7 8 9 10 11

第一段標示系統資訊,第二段標示日期,後面的數字標示message id。

個人訊息建立一個集合:

SADD user:12345:read 1 2 3 4

第一段標示使用者資訊集合,第二段標示使用者id,下一段標示訊息型別為已讀,後面的數字標示message id。

關於訂閱訊息如下:

SADD rss:xiaocao 12 13 14 15

那麼你就收到小草的訂閱訊息,訊息ID分別是 12, 13, 14, 15

還有很重要的訊息資料儲存,

HMSET message:12 title 標題 content 內容 date 2015-08-03

Python建立資料庫的例子就是:

import redis,time,threading,random
pool = redis.ConnectionPool(host='localhost', port=6379, db=1)
rs = redis.Redis(connection_pool=pool)

rs.sadd("user:123:read", "1", "2")
rs.sadd("user:123:unread", "4", "5", "6")
rs.sadd("system:2015-08-03", "7", "8", "9", "10", "11")
rs.sadd("rss:xiaocao", "12", "13", "14", "15", "11")

for i in range(15):
    rs.hset("message:"+str(i), "title", "title=>"+str(random.uniform(1, 99999)))
    rs.hset("message:"+str(i), "content","content=>"+str(time.time()))
    rs.hset("message:"+str(i), "date", str(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())))

參考:

-by小草

相關推薦

訊息設計實現

0x01.About 最近在處理系統訊息模組,查閱了很多實踐案例,各有針對性。 首先站內訊息主要包括:個人訊息(評論,點贊),系統訊息,訂閱訊息,私信。 其中,訂閱區分使用者群,即系統訊息是一個特殊的所有人訂閱的訂閱訊息,特點是一對多。 前三個實時性比較低,最後一

《Linux設計實現》讀書筆記(八)- 中斷下半部的處理

sym dmesg 重新編譯 warn dad style lsp 之前 res 在前一章也提到過,之所以中斷會分成上下兩部分,是由於中斷對時限的要求非常高,需要盡快的響應硬件。 主要內容: 中斷下半部處理 實現中斷下半部的機制 總結中斷下半部的實現 中斷實現

《Linux設計實現》讀書筆記(十二)- 存管理

enable vmalloc 緩沖 turn lean png border 編譯 不一致 內核的內存使用不像用戶空間那樣隨意,內核的內存出現錯誤時也只有靠自己來解決(用戶空間的內存錯誤可以拋給內核來解決)。 所有內核的內存管理必須要簡潔而且高效。 主要內容: 內

《Linux設計實現》讀書筆記(十六)- 頁高速緩存和頁回寫

第一次 源碼 進行 lose 減少 文件緩存 掩碼 recycle 創建 主要內容: 緩存簡介 頁高速緩存 頁回寫 1. 緩存簡介 在編程中,緩存是很常見也很有效的一種提高程序性能的機制。 linux內核也不例外,為了提高I/O性能,也引入了緩存機

Linux設計實現高清版pdf免費下載

以及 處理機 指定 ddr 中斷處理 回寫 2.3 結合 用處 下載地址:網盤下載 備用地址:網盤下載 內容簡介編輯《Linux內核設計與實現(原書第3版)》基於Linux 2.6.34內核詳細介紹了Linux內核系統,覆蓋了從核心內核系統的應用到內核設計與實

Linux設計實現 總結筆記(第四章)進程調度

什麽 原則 好的 nic 調度系統 相交 中間 使用 就是 進程調度 調度程序負責決定將哪個進程投入運行,何時運行以及運行多長時間。 調度程序沒有太復雜的原理,最大限度地利用處理器時間的原則是,只要有可以執行的進程,那麽就總會有進程正在執行。 多任務 多任務系統可以劃分

Linux設計實現 總結筆記(第五章)系統調用

總結筆記 其余 筆記 運行 six 應用 osi 虛擬系統 抽象接口 系統調用 內核提供了用戶進程和內核交互的接口,使得應用程序可以受限制的訪問硬件設備。 提供這些接口主要是為了保證系統穩定可靠,避免應用程序恣意妄行。 一、內核通信 系統調用在用戶空間進程和硬件設備之間

大中型企業網新聞資訊系統的設計實現——論文隨筆(十八)

一、基本資訊 標題:大中型企業內網新聞資訊系統的設計與實現 時間:2015-10 出版源:蘇州大學 領域分類:系統架構和設計 二、研究背景 問題定義:近年來,文化體制改革快速推進,新聞媒體產業也在快速發展,大中型企業對公司新聞報道工作越加重視,企業品牌建設工作更多通過新聞宣傳的方式來實現。許多大型企業將

OpenStack設計實現(四)訊息匯流排(AMQP)

在西方有一句諺語,叫做“Don’t Reinvent the Wheel!”。直譯過來就是不要在重新發明輪子了。也就是說我們應該避免做一些重複性的工作,如果一個東西別人已經做過了,那麼我們拿來直接用就行了,沒有必要重新制作,這一點在軟體開發裡尤為突出。所以在Op

Java訊息系統簡單設計實現

前言:由於導師在我的畢設專案里加了訊息系統(本來想水水就過的..),沒辦法...來稍微研究研究吧..簡單簡單... 需求分析 我的畢設是一個部落格系統,類似於簡書這樣的,所以訊息系統也類似,在使用者的訊息裡包含了有:喜歡和贊、評論、關注、私信這樣的一類東西,這樣的一個系統應該包含以下的功能:

開源訊息佇列QMQ的設計實現理念

文章概要 背 景 2012 年,隨著公司業務的快速增長,公司當時的單體應用架構很難滿足業務快速增長的要求,和其他很多公司一樣,去哪兒網也開始了服務化改造,按照業務等要素將原來龐大的單體應用拆分成不同的服務。那麼在進行服務化改造之前首先就是面臨是服務化基礎設施的技術選型,其中最重要的就是服

簡單易用的訊息佇列框架的設計實現

作者:李豔鵬,支付平臺架構師,專注線上和線下支付平臺的應用架構和技術架構的規劃與落地,負責交易、支付、渠道、賬務、計費、風控、對賬等系統的設計與實現,在移動支付、聚合支付、合規賬戶、掃碼支付、標記化支付等業務場景上有產品應用架構規劃的經驗。微信:rober

jQuery架構設計實現(2.1.4版本)

需要 引入 hasclass 8.4 uri and hub 組織 移除 市面上的jQuery書太多了,良莠不齊,看了那麽多總覺得少點什麽 對"幹貨",我不喜歡就事論事的寫代碼,我想把自己所學的知識點,代碼技巧,設計思想,代碼模式能很好的表達出來,所以考慮通過分析jQuer

畢業設計-證券宣傳手機微網站的設計實現

信息 browser .com 接受 熱點 互聯網 計算機網絡 業務 結構 本文介紹基於.net的證券公司宣傳微網站手機網頁的設計與實現方法。 隨著計算機技術的快速發展,基於Web的計算機網絡金融、證券宣傳或交易網站已成為現代金融理財發展的熱點,B/S(Browser/Se

MVC實戰之排球計分(四)—— View設計實現

service family 角色 元素 需要 rom 之前 con xsl (view)視圖 視圖是用戶看到並與之交互的界面。對老式的Web應用程序來說,視圖就是由HTML元素組成的界面,在新式的Web應用程序中,HTML依舊在視圖中扮演著重要的角色,但一些新的技術已層出

MVC實戰之排球計分(五)—— Controller的設計實現

需要 strong 技術 ret web src alt 點擊 cnblogs 控制器 控制器接受用戶的輸入並調用模型和視圖去完成用戶的需求。所以當單擊Web頁面中的超鏈接和發送HTML表單時, 控制器本身不輸出任何東西和做任何處理。它只是接收請求並決定調用哪個模型構件去處

stm32視頻教程分享:心率檢測儀的設計實現

stm32視頻教程分享:心率檢測儀的設計與實現 STM32系列是基於專為要求高性能、低成本、低功耗的嵌入式應用專門設計的ARM Cortex-M3內核。 本項目主要講述了通過心律傳感器采集我們的心律數據,然後通過串口傳送到上位機中,上位機用Qt

MVC之排球比賽計分程序 ——(四)視圖的設計實現

元素 role view logs image 技術 size 之前 log (view)視圖 視圖是用戶看到並與之交互的界面。對老式的Web應用程序來說,視圖就是由HTML元素組成的界面,在新式的Web應用程序中,HTML依舊在視圖中扮演著重要的角色,但一些新的技術

MVC之排球比賽計分程序 ——(三)model類的設計實現

比賽 用戶 count class 包括 result 控制 類的設計 可能 實體類是現實實體在計算機中的表示。它貫穿於整個架構,負擔著在各層次及模塊間傳遞數據的職責。一般來說,實體類可以分為“貧血實體類”和“充血實體類”,前者僅僅保存實體的屬性,而後者還包含一些實體間的關

模型類的設計實現(四)

介紹 傳遞數據 規則 添加 play using ota 實體類 重要 實體類是現實實體在計算機中的表示。它貫穿於整個架構,負擔著在各層次及模塊間傳遞數據的職責。 一般來說,實體類可以分為“貧血實體類”和“充血實體類”,前者僅僅保存實體的屬性,而後者還包含一些實體間的關系與