傳統MySQL+Memcached架構遇到的問題mysql
實際MySQL 是適合進行海量存儲的,經過Memcached將熱點數據加載到cache,加速訪問,不少公司都曾經使用過這樣的架構,但隨着業務數據量的不斷增長,和訪問量的持續增加,咱們遇到了不少問題:web
1. MySQL須要不斷的進行拆庫拆表,Memcached也需不斷跟着擴容,擴容和維護工做佔據大量開發時間。sql
2. Memcached與MySQL數據庫數據一致性問題。mongodb
3. Memcached數據命中率低或down機,大量訪問直接穿透到DB,MySQL沒法支撐。數據庫
4. 跨機房cache同步問題。json
衆多NoSQL百花齊放,如何選擇網絡
最近幾年,業界不斷涌現出不少各類各樣的NoSQ產品,那麼如何才能正確地使用好這些做品,最大化地發揮其長處,是咱們須要深刻研究和思考的問題,實際歸根結底最重要的是瞭解這些產品的定位,而且瞭解到每款產品的tradeoffs,在實際應用中作到揚長避短,整體上這些NoSQL主要用於解決如下幾種問題數據結構
1. 少許數據存儲,高速讀寫訪問。此類產品經過數據所有in-momery的方式保證高速訪問,同時提供數據落地的功能,實際這正是Radis最主要的適用場景。多線程
2. 海量數據存儲,分佈式系統支持,數據一致性保證,方便的集羣節點添加/刪除。架構
3. 這方面最具表明性的是dynamo和bigtables 2篇論文所闡述的思路。前者是一個徹底無中心的設計,節點之間經過gossip方式傳遞集羣信息,數據保證最終一致性,後者是一箇中心化的方案設計,經過相似一個分佈式鎖服務來保證強一致性,數據寫入先寫內存和redo log,而後按期compat歸併到磁盤上,將隨機寫優化爲順序寫,提升寫入性能。
4. Schema free,auto-sharding等。好比目前常見的一些文檔數據庫都是支持schema-free的,直接存儲json格式數據,而且支持auto-sharding等功能,好比mongodb。
面對這些不一樣類型的NoSQL產品,咱們須要根據咱們的業務場景選擇最合適的產品。
Redis適用場景,如何正確的使用
前面已經分析過,Redis最適合全部數據in-momory的場景,雖然Redis也提供持久化功能,但實際更多的是一個disk-backed的功能,跟傳統意義上的持久化有比較大的差異,那麼可能你們就會有疑問,彷佛Redis更像一個增強版的Memcached,那麼什麼時候使用Memcached,什麼時候使用Redis呢?
1.網絡IO模型
Memcached是多線程,非阻塞IO複用的網絡模型,分爲監聽主線程和worker子線程,監聽線程監聽網絡鏈接,接受請求後,將鏈接描述字pipe 傳遞給worker線程,進行讀寫IO, 網絡層使用libevent封裝的事件庫,多線程模型能夠發揮多核做用,可是引入了cache coherency和鎖的問題,好比,Memcached最經常使用的stats 命令,實際Memcached全部操做都要對這個全局變量加鎖,進行計數等工做,帶來了性能損耗。
(Memcached網絡IO模型)
Redis使用單線程的IO複用模型,本身封裝了一個簡單的AeEvent事件處理框架,主要實現了epoll、kqueue和select,對於單純只有IO操做來講,單線程能夠將速度優點發揮到最大,可是Redis也提供了一些簡單的計算功能,好比排序、聚合等,對於這些操做,單線程模型實際會嚴重影響總體吞吐量,CPU計算過程當中,整個IO調度都是被阻塞住的。
2.內存管理方面
Memcached使用預分配的內存池的方式,使用slab和大小不一樣的chunk來管理內存,Item根據大小選擇合適的chunk存儲,內存池的方式能夠省去申請/釋放內存的開銷,而且能減少內存碎片產生,但這種方式也會帶來必定程度上的空間浪費,而且在內存仍然有很大空間時,新的數據也可能會被剔除,緣由能夠參考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/
Redis使用現場申請內存的方式來存儲數據,而且不多使用free-list等方式來優化內存分配,會在必定程度上存在內存碎片,Redis跟據存儲命令參數,會把帶過時時間的數據單獨存放在一塊兒,並把它們稱爲臨時數據,非臨時數據是永遠不會被剔除的,即使物理內存不夠,致使swap也不會剔除任何非臨時數據(但會嘗試剔除部分臨時數據),這點上Redis更適合做爲存儲而不是cache。
Redis更適合做爲存儲而不是cache。
3.數據一致性問題
Memcached提供了cas命令,能夠保證多個併發訪問操做同一份數據的一致性問題。 Redis沒有提供cas 命令,並不能保證這點,不過Redis提供了事務的功能,能夠保證一串 命令的原子性,中間不會被任何操做打斷。
4.存儲方式及其它方面
Memcached基本只支持簡單的key-value存儲,不支持枚舉,不支持持久化和複製等功能
Redis除key/value以外,還支持list,set,sorted set,hash等衆多數據結構,提供了KEYS
進行枚舉操做,但不能在線上使用,若是須要枚舉線上數據,Redis提供了工具能夠直接掃描其dump文件,枚舉出全部數據,Redis還同時提供了持久化和複製等功能。
5.關於不一樣語言的客戶端支持
在不一樣語言的客戶端方面,Memcached和Redis都有豐富的第三方客戶端可供選擇,不過由於Memcached發展的時間更久一些,目前看在客戶端支持方面,Memcached的不少客戶端更加成熟穩定,而Redis因爲其協議自己就比Memcached複雜,加上做者不斷增長新的功能等,對應第三方客戶端跟進速度可能會趕不上,有時可能須要本身在第三方客戶端基礎上作些修改才能更好的使用。
根據以上比較不難看出,當咱們不但願數據被踢出,或者須要除key/value以外的更多數據類型時,或者須要落地功能時,使用Redis比使用Memcached更合適。
Redis除了做爲存儲以外還提供了一些其它方面的功能,好比聚合計算、pubsub、scripting等,對於此類功能須要瞭解其實現原理,清楚地瞭解到它的侷限性後,才能正確的使用,好比pubsub功能,這個實際是沒有任何持久化支持的,消費方鏈接閃斷或重連之間過來的消息是會所有丟失的,又好比聚合計算和scripting等功能受Redis單線程模型所限,是不可能達到很高的吞吐量的,須要謹慎使用。
總的來講Redis做者是一位很是勤奮的開發者,能夠常常看到做者在嘗試着各類不一樣的新鮮想法和思路,針對這些方面的功能就要求咱們須要深刻了解後再使用。
後續關於Redis文章計劃:
關於做者
田琪,目前負責新浪微博平臺底層架構與研發工做,以前曾擔任搜狐白社會實時遊戲平臺核心架構工做,主要關注webgame, 分佈式存儲,nosql 和 erlang 等領域,目前主要從事mysql源代碼的一些深刻研究工做,浪微博: http://weibo.com/bachmozart。