要是不清楚什么是feed,google之。?
Feed是sns類應用的核心和最復雜的部分,就是sina微博中看到的“我關注的人”的消息。像人人網中的“新鮮事”等等,都是一個東西。你想啊,你關注了幾千人,又被幾千人關注,你發了一個消息,另外幾千人怎么看到哪?拿數據庫做join和in操作肯定立刻掛。而且像sina weibo,數據和訪問量龐大,怎么實現哪?這其實就是傳說中的推和拉的選擇,人人網寫過一篇文章:http://news.csdn.net/a/20100726/277273.html,簡單來說以推為主體。我猜測可能在某些情況下會使用拉,例如這個賬號很久不登錄,太不活躍,給他推東西純屬浪費。嗯。。。,這方面也歡迎一起來猜猜。?
基于這些,我猜測的第1版架構圖(我們現在就是這樣做的,規模比較小,還看不出問題):?
?
整個架構基于memcached + mysql,圖中分了ABC三個區域。所有的消息存儲在mysql中,無論推送給多少人,只存儲一份。另外有一個索引表,用來記錄推送關系,推送給1000個人,就增加1000條記錄,也就是圖中的A。當發生查詢時,從索引表中根據用戶編號進行一次簡單查詢(基于用戶編號為索引和條件的select),拿到索引結果后,進入B,從memcached中讀取實際信息。如果不存在或者不全,進入C,根據索引信息讀取網友實際發表或者轉載的內容,用模板生成消息并存儲到memcached中,然后返回來。?
在整個過程中,B是memcached集群,性能應該問題不大。C是cache后面的東西,其中的數據庫查詢也是基于索引表中給的對象主鍵,分表條件等進行的分庫分表基于主鍵的查詢,性能問題應該也不大。關鍵是A區。我們現在的方案是用guzz框架把索引表分到單獨的一組數據庫中,然后根據用戶id進行切表,每個人保留最多200條最新消息的索引。總的來說,每張表的大小還在控制內。對于像#話題#等也是一樣的,建立索引表分發。無論怎樣,實際的消息只有一份。?
我猜測,sina微博第一版系統應該就是這樣。架構簡單實用。?
但隨著規模的擴大,A區索引表肯定會逐步出現大量性能問題。要升級到第二,第三版。這兩個之間或許是一步到位的。?
第二第三版架構猜測:?
A區的性能問題不是mysql能夠解決的,但幸好A區的數據結構非常簡單。就是以 用戶id+某個動態功能 為key下的一個固定大小的索引集合。最簡單的辦法就是把mysql換成nosql,這個數據結構用nosql應該非常容易實施。我沒有用過nosql,但通過資料來看,相比mysql肯定是一大性能提升。我們暫且推測其為第二版方案吧。歡迎實際用過nosql的來談談行不行。?
我們假設,第二版方案也解決不了問題。A區的性能問題太大了,怎么辦?如果這樣,我想索引系統只能是自己做了,誰也靠不住。我有個猜測,歡迎討論。看下圖。?
?
這個架構是完全為feed定制的,我們為每個 用戶id+某個動態功能 分配一個磁盤block。在索引表中,我們知道每條索引記錄的大小是固定的(假設每條1k大小),而為用戶提供的最多最新動態數也是固定的(假設200條)。那么我們這個block就分配固定的201K,前面的1k是頭信息,后面的200k存儲最多200條的索引記錄。?
在頭信息中,記錄這個塊操作的系統版本號(升級使用),用戶信息,操作的偏移量,總動態數等等。當插入一條新索引時,根據操作偏移量直接定位位置,寫入;如果已經寫到第200條,回到第一條覆蓋寫。讀取的時候,根據偏移量數據直接讀。因為記錄大小固定,block維護簡單,順序讀寫,效率肯定不差。而這些block文件塊,將存儲在一套分布式文件系統中,依靠還算成熟的hadoop技術,無限擴展這個大集群。?
相比數據庫的優勢,還省去了清理過期數據的問題。?
這里面沒有討論block塊緩存的問題,這是分布式文件系統的工作。對于不同的動態,可能block的大小會不一樣,這都是可以的。?
不知道猜的對不對。
Feed是sns類應用的核心和最復雜的部分,就是sina微博中看到的“我關注的人”的消息。像人人網中的“新鮮事”等等,都是一個東西。你想啊,你關注了幾千人,又被幾千人關注,你發了一個消息,另外幾千人怎么看到哪?拿數據庫做join和in操作肯定立刻掛。而且像sina weibo,數據和訪問量龐大,怎么實現哪?這其實就是傳說中的推和拉的選擇,人人網寫過一篇文章:http://news.csdn.net/a/20100726/277273.html,簡單來說以推為主體。我猜測可能在某些情況下會使用拉,例如這個賬號很久不登錄,太不活躍,給他推東西純屬浪費。嗯。。。,這方面也歡迎一起來猜猜。?
基于這些,我猜測的第1版架構圖(我們現在就是這樣做的,規模比較小,還看不出問題):?

整個架構基于memcached + mysql,圖中分了ABC三個區域。所有的消息存儲在mysql中,無論推送給多少人,只存儲一份。另外有一個索引表,用來記錄推送關系,推送給1000個人,就增加1000條記錄,也就是圖中的A。當發生查詢時,從索引表中根據用戶編號進行一次簡單查詢(基于用戶編號為索引和條件的select),拿到索引結果后,進入B,從memcached中讀取實際信息。如果不存在或者不全,進入C,根據索引信息讀取網友實際發表或者轉載的內容,用模板生成消息并存儲到memcached中,然后返回來。?
在整個過程中,B是memcached集群,性能應該問題不大。C是cache后面的東西,其中的數據庫查詢也是基于索引表中給的對象主鍵,分表條件等進行的分庫分表基于主鍵的查詢,性能問題應該也不大。關鍵是A區。我們現在的方案是用guzz框架把索引表分到單獨的一組數據庫中,然后根據用戶id進行切表,每個人保留最多200條最新消息的索引。總的來說,每張表的大小還在控制內。對于像#話題#等也是一樣的,建立索引表分發。無論怎樣,實際的消息只有一份。?
我猜測,sina微博第一版系統應該就是這樣。架構簡單實用。?
但隨著規模的擴大,A區索引表肯定會逐步出現大量性能問題。要升級到第二,第三版。這兩個之間或許是一步到位的。?
第二第三版架構猜測:?
A區的性能問題不是mysql能夠解決的,但幸好A區的數據結構非常簡單。就是以 用戶id+某個動態功能 為key下的一個固定大小的索引集合。最簡單的辦法就是把mysql換成nosql,這個數據結構用nosql應該非常容易實施。我沒有用過nosql,但通過資料來看,相比mysql肯定是一大性能提升。我們暫且推測其為第二版方案吧。歡迎實際用過nosql的來談談行不行。?
我們假設,第二版方案也解決不了問題。A區的性能問題太大了,怎么辦?如果這樣,我想索引系統只能是自己做了,誰也靠不住。我有個猜測,歡迎討論。看下圖。?

這個架構是完全為feed定制的,我們為每個 用戶id+某個動態功能 分配一個磁盤block。在索引表中,我們知道每條索引記錄的大小是固定的(假設每條1k大小),而為用戶提供的最多最新動態數也是固定的(假設200條)。那么我們這個block就分配固定的201K,前面的1k是頭信息,后面的200k存儲最多200條的索引記錄。?
在頭信息中,記錄這個塊操作的系統版本號(升級使用),用戶信息,操作的偏移量,總動態數等等。當插入一條新索引時,根據操作偏移量直接定位位置,寫入;如果已經寫到第200條,回到第一條覆蓋寫。讀取的時候,根據偏移量數據直接讀。因為記錄大小固定,block維護簡單,順序讀寫,效率肯定不差。而這些block文件塊,將存儲在一套分布式文件系統中,依靠還算成熟的hadoop技術,無限擴展這個大集群。?
相比數據庫的優勢,還省去了清理過期數據的問題。?
這里面沒有討論block塊緩存的問題,這是分布式文件系統的工作。對于不同的動態,可能block的大小會不一樣,這都是可以的。?
不知道猜的對不對。