亞寵展、全球寵物產業風向標——亞洲寵物展覽會深度解析
1108
2022-05-28
1 系統分析
1.1 Scenario 場景
注冊、登錄、查詢、用戶信息修改,哪個需求量最大?
支持100M DAU。注冊,登錄,信息修改 QPS 約:
100M * 0.1 / 86400 ~ 100
0.1 = 平均每個用戶每天登錄+注冊+信息修改
Peak = 100 * 3 = 300
查詢QPS約
100 M * 100 / 86400 ~ 100k
100 = 平均每個用戶每天與查詢用戶信息相關的操作次數(查看好友,發信息,更新消息主頁)
Peak = 100k * 3 = 300 k
1.2 Service 服務
AuthenticationService 負責登錄注冊
UserService 負責用戶信息存儲與查詢
FriendshipService 負責好友關系存儲
1.3 Storage
QPS 與 常用數據存儲系統。
MySQL、PosgreSQL 等 SQL 數據庫性能約 1k QPS
MongoDB、Cassandra 等硬盤型NoSQL數據庫性能約 10k QPS
Redis / Memcached 等內存型NoSQL數據庫性能約100k ~ 1m QPS
(根據機器性能和硬盤數量及硬盤讀寫速度會有區別)
用戶系統特點:讀非常多,寫非常少。讀多寫少的系統一定要使用 Cache 進行優化。
使用緩存,也就會帶來數據不一致問題,數據庫和緩存是兩臺機器,兩套系統,并不支持加鎖。如果是用一些第三方分布式鎖,會導致存取效率降低,得不償失。業界最常用的方法:
database.set(key, user); cache.delete(key)
class UserService { def getUser(self, user_id): key = 'user::%s' % user_id user = cache.get(user) if user: return user user = db.get(user_id) cache.set(key, user) return user def setUser(self, user): key = 'user::%s' % user.id db.set(user) cache.delete(key) }
并發情況下依舊會出問題,在getUser執行到如下兩行之間時:
另一個進程執行setUser(),cache 里會放入舊數據
問題2:db set 成功,cache delete 失敗
但這兩種情況發生概率<< cache.delete + db.set。
解決一致性問題?
利用 cache 的 TTL。
任何一個 cache 中的 key 都不要永久有效,設置一個短暫有效時間,如 7 天。則即便在極低概率下出現數據不一致,也就最多不一致7天。即允許數據庫和緩存有“短時”不一致,但最終一致。
在每次數據修改的時候,會在 cache 中 delete 這個數據。若寫多讀少,則此時 cache 沒有任何優化效果。
Authentication Service 登錄系統
Session 會話
用戶 Login 后,為之創建一個 session 對象
并把 session_key 返回給瀏覽器,讓瀏覽器存儲起來
瀏覽器將該值記錄在瀏覽器的 cookie 中
用戶每次向服務器發送的訪問,都會自動帶上該網站所有的 cookie
此時服務器拿到 cookie 中的 session_key,在 Session Table 中檢測是否存在,是否過期
Cookie
HTTP 協議中瀏覽器和服務器的溝通機制,服務器把一些用于標記用戶身份的信息,傳遞給瀏覽器,瀏覽器每次訪問任何網頁鏈接的時候,都會在 HTTP 請求中帶上所有的該網站相關的Cookie 信息。Cookie 可理解為一個 Client 端的 hash table。
Session 記錄過期以后,服務器會主動刪除么?
只支持在一臺機器登陸和在多臺機器同時登陸的區別是什么?
Session 適合存在什么數據存儲系統中
Friendship Service
好友關系的存儲與查詢
雙向好友關系
單向好友關系
Twitter、Instagram、微博
存在 SQL 數據庫時:
查詢x所有的關注對象
select * from friendship where from_user_id=x
查詢x所有的粉絲:
select * from friendship where to_user_id=x;
存在 NoSQL 數據庫時:
Friendship:
雙向好友關系
微信,Facebook,WhatsApp
select * from friendship where smaller_user_id = x or bigger_user_id=x
為何區分 smaller / bigger?
SQL 可以按照這種方案,但NoSQL 很多不支持 Multi-index 不能使用這種方案。
select * from friendship where from_user_id=x
NoSQL 和 SQL 都可按照這種方案
你覺得哪種更好呢?
Cassandra
三層結構的 NoSQL 數據庫
? http://www.lintcode.com/problem/mini-cassandra/
第一層:row_key
第二層:column_key
第三層:value
Cassandra 的 Key = row_key + column_key,同一個 Key只對應一個 value
結構化信息如何存儲?
將其他需要同時存儲的數據,序列化(Serialize)到 value 里進行存儲。
Serialization:把一個 object / hash 序列化為一個 string,比如把一棵二叉樹序列化
? http://www.lintcode.com/problem/binary-tree-serialization/
row_key
又稱為 Hash Key, Partition Key。Cassandra 會根據這個 key 算一個 hash 值,然后決定整條數據存儲在哪兒。無法 Range Query
常用:user_id
Column Key
insert(row_key, column_key, value)
任何一條數據,都包含上面三個部分。可指定 column_key 按何排序。
Cassandra 支持這樣的“范圍查詢”:
query(row_key, column_start, column_end)
可以是復合值,如 timestamp + user_id
SQL vs NoSQL
SQL的column是在Schema中預先指定好的,不能隨意添加
一條數據一般以 row 為單位(取出整個row作為一條數據)
NoSQL的column是動態的,無限大,可以隨意添加
一條數據一般以 grid 為單位,row_key + column_key + value = 一條數據
只需要提前定義好 column_key 本身的格式(是一個 int 還是一個 int+string)
Cassandra 存儲Friendship表
Cassandra 存儲 NewsFeed
Friendship Table適合什么數據庫?
SQL 和 NoSQL 的選擇標準
原則1 大部分情況,都能用
原則2 需要支持事務,則禁選 NoSQL
原則3 想在什么地方偷懶,很大程度決定選什么數據庫
SQL
結構化數據,自由創建索引
NoSQL
分布式,Auto-scale,Replica
原則4 一般一個網站會同時用多種數據庫系統
不同的表單放在不同的數據庫。
User Table 存在哪兒?
大部分公司選擇了 SQL,因為信任度,Multi-Index!
Friendship 存在哪兒?
大部分公司選擇了 NoSQL,因為數據結構簡單,都是 key-value 的查詢/存儲需求,NoSQL效率更高!
SQL 數據庫
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。