Unread架構(gòu)介紹

2018-02-24 15:46 更新

原文出處:http://weibo.com/p/1001643880172431480781
作者:唐揚,@唐揚TY

未讀提醒功能在各種社交平臺服務中較為常見,在微博中這些功能由Unread服務來提供。看似簡單的功能,當請求量級達到一定規(guī)模后,成本、性能、穩(wěn)定性的平衡將是架構(gòu)設(shè)計的重點。

大綱

一 微博中Unread服務業(yè)務場景

在以timeline為核心的微博業(yè)務中, 未讀數(shù)場景出現(xiàn)的頻率較高,它可以是這樣的…

也可以是這樣的…

二 從架構(gòu)角度對各種業(yè)務場景的抽象

通過分析和比較這些未讀場景,我們抽象了unread服務中設(shè)計到的三種主要操作:

1.?incr:增加未讀數(shù)

2.?reset:未讀數(shù)清零

3.?get:獲取未讀數(shù)

我們發(fā)現(xiàn)unread服務中g(shù)et操作是典型的無觸發(fā)操作,即不需要用戶執(zhí)行任何操作都會對服務器造成請求。正是這個特點給unread服務帶來如下問題:

1.?高并發(fā):高峰期單一業(yè)務的qps達到10萬+

2.?性能要求高:接口4個9的響應時間在10ms

為了解決上述問題,unread架構(gòu)針對不同的業(yè)務場景設(shè)計了不同的方案,保證了服務的高性能、高可用和可擴展。本文主要針對三種典型的未讀數(shù)場景介紹微博平臺是如何設(shè)計解決方案的。

場景一.?一對一行為未讀提醒場景

在這種場景下,用戶的某一個操作只會影響一個用戶的未讀數(shù)字。典型的場景有:@未讀提醒、評論未讀提醒、贊評論提醒等等。

針對這種場景,我們采用最簡單的解決方案:為每一個用戶存儲一份未讀數(shù)字,如下圖

在設(shè)計的實現(xiàn)中,由于存儲容量可控,我們采用redis存儲未讀數(shù)。相比于通常使用的mysql+mc的存儲解決方案,redis有以下的優(yōu)勢:

1.?存儲一體化,避免了緩存和持久化存儲之間一致性的問題

2.?快速恢復

這個設(shè)計方案主要基于如下的考慮:

1.?簡單直觀

2.?性能能夠達到SLA,每次操作只需要訪問一次資源

場景二.?全量打點場景

打點主要指微博官方客戶端中的一些弱提醒功能,見下圖中的紅點

而全量打點指對全量用戶都增加未讀提醒紅點??紤]到目前微博的用戶量,如果采用第一種場景的方案,打點過程會存在很大的延遲。因此我們采用了基于tag的解決方案。

1.?存儲公共的時間戳global

2.?每一個用戶存儲一個時間戳

3.?打點時,更新global時間戳為當前時間

4.?消點時,更新用戶的時間戳為global時間戳

5.?如果用戶時間戳小于global時間戳,則有點;否則沒有點

這個方案適用于用戶間存在共享存儲,且共享存儲有限的場景。在這種場景下,我們?yōu)槊恳粋€用戶存儲一個tag用來記錄用戶在共享存儲中的已讀位置,這樣就可以通過比較這個已讀位置獲得用戶的未讀數(shù)。

在實際的應用過程中,我們通常會使用本地緩存來解決訪問共享存儲的極端峰值。這種基于已讀位置的解決方案雖然能很好的解決全量打點的問題,但是面對訪問量最大的微博未讀數(shù)場景卻是無能為力,原因有二:

1.?用戶的feed是無限的,不存在共享存儲,全部存儲下來的成本很高

2.?在高并發(fā)下獲取未讀數(shù)操作性能衰減嚴重

我們采用了下面這種方案來解決微博未讀數(shù)問題。

場景三.?微博未讀數(shù)場景

眾所周知,微博未讀數(shù)就是微博主feed未讀數(shù),當我關(guān)注的人發(fā)表一條微博,我的微博未讀數(shù)提醒就會加一。

對于微博微博數(shù)場景,我們采用了基于snapshot的解決方案,具體如圖所示:

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號