有個想法,用兩個伺服器,node處理請求,把資料全部push到 redis緩衝隊列中,另一個php伺服器不斷的pop這個隊列裡的資料然後與mysql互動做持久化。。。大家覺得這麼做怎麼樣 ?
回複內容:
如其它答案,基本有兩種解決方案
1. Redis內建的PUB/SUB機制,即發布-訂閱模式。這種模式生產者(producer)和消費者(consumer)是1-M的關係,即一條訊息會被多個消費者消費,當只有一個消費者時即可以看做一個1-1的訊息佇列,但這種方式並不適合題主的情境。首先,資料可靠性的無法保障,題主的資料最終需要落庫,如果訊息丟失、Redis宕機部分資料沒有持久化甚至突然的網路抖動都可能帶來資料的丟失,應該是無法忍受的。其次,擴充不靈活,沒法通過多加consumer來加快消費的進度,如果前端寫入資料太多,同步會比較慢,資料不同步的狀態越久,風險越大,當然可以通過channel拆分的方式來解決,雖然不靈活,但可以規避。這種方案更適合於對資料可靠性要求不高,比如一些統計日誌打點。
2. Redis的PUSH/POP機制,利用的Redis的列表(lists)資料結構。比較好的使用模式是,生產者lpush訊息,消費者brpop訊息,並設定逾時時間,可以減少redis的壓力。這種方案相對於第一種方案是資料可靠性提高了,只有在Redis宕機且資料沒有持久化的情況下遺失資料,可以根據業務通過AOF和縮短持久化間隔來保證很高的可靠性,而且也可以通過多個client來提高消費速度。但相對於專業的訊息佇列來說,該方案訊息的狀態過於簡單(沒有狀態),且沒有ack機制,訊息取出後消費失敗依賴於client記錄日誌或者重新push到隊列裡面。
最後再來看題主的需求,是希望先寫Redis,再非同步同步到mysql裡面,期望資料的最終一致性。這樣帶來的好處是前端寫的請求飛速啊(不用落盤當然快),問題是很複雜,而且不太合理。假設是合理的話,就應該選擇一個更可靠的訊息中介軟體,比如Redis作者開源的Disque,或者阿里開源RocketMQ,以及基於Golang的nsq等,Redis更適合用來存資料。
為什麼說題主的需求不合理?
類似於這種先寫緩衝再同步到DB的,目的是為了減少DB壓力,提升前端API效能。題主的方案雖然能做到這兩點,但忽略了根本的一點:資料不管存到哪裡,都是用來訪問(使用)的。但在題主的方案裡,寫入Redis的資料除了同步到DB裡,不接任何訪問量,並沒有什麼卵用,最後DB讀的壓力上來了,還得把資料重新LOAD回Redis裡面,得不償失。
什麼樣的架構更合理?
只簡單說一下。
非同步寫入,在百度、58同城使用很多,基本的架構是先抽象出對象訪問層(或者只是緩衝層),對外屏蔽資料來源(Redis、mysql、others)。對象訪問層對於某類資料的格式是定義好的,寫的請求來了直接寫入緩衝(Redis),這樣前端的讀請求就直接讀緩衝了,這樣存入的資料就有意義(當然了,接了大大的讀的量啊)。然後是資料落地(最終一致性問題),簡單的可以讀RDB檔案(即時性不高),複雜一點的可以實現Redis的主從同步協議(即時性高於前一種)。第一種簡單,效率低,第二種複雜,效率高。
從Redis談起(三)—— Redis和訊息中介軟體
這邊文章比較詳細得講解了Redis和訊息中介軟體
謝謝,希望對大家有協助。
===============================================================
歡迎各位關注我運營的wx公眾號 “中介軟體架構”,號:middlewarearch,最近有在更新Redis相關的文章,會持續更新mysql proxy、Redis、nginx、訊息中介軟體、RPC架構相關的文章,謝謝。
用redis的list, 先lpush, 然後一個線程去rpop資料處理。如果系統量不大,redis的list push,pop足夠了, 如果量大盡量用成熟一些的MQ,不過會重一些,具體要看情境。redis本身就支援pub/sub模式,可以作為訊息佇列處理,參見 Command reference
按題主的情境,需要配置redis的持久化儲存,否則可能會出現資料沒有儲存到mysql中的情形。pubsub解決的是廣播問題,poppush才是解決隊列問題。lpush rpoplpush和lpop適合樓主Reference [2.3]
什麼類的資料?
要求不是很高的話可以用logstash
目前官方沒有mysql的output plugins
輸入源 redis支援lpush和lpop和、pub/sub模式,改改設定檔就行了,不用redis,用nsq、 kafka之類也有對應的外掛程式
輸出外掛程式看官方文檔,支援mongodb和elasticsearchlpush/rpop類比堆棧去存取。和我畢業設計做的爬蟲一樣,一個進程持續往redis裡rpush資料,另一個進程lpop