paulwong

          為什么使用 Redis及其產(chǎn)品定位

          傳統(tǒng)MySQL+ Memcached架構(gòu)遇到的問(wèn)題

          實(shí)際MySQL是適合進(jìn)行海量數(shù)據(jù)存儲(chǔ)的,通過(guò)Memcached將熱點(diǎn)數(shù)據(jù)加載到cache,加速訪問(wèn),很多公司都曾經(jīng)使用過(guò)這樣的架構(gòu),但隨著業(yè)務(wù)數(shù)據(jù)量的不斷增加,和訪問(wèn)量的持續(xù)增長(zhǎng),我們遇到了很多問(wèn)題:

          1. MySQL需要不斷進(jìn)行拆庫(kù)拆表,Memcached也需不斷跟著擴(kuò)容,擴(kuò)容和維護(hù)工作占據(jù)大量開(kāi)發(fā)時(shí)間。

          2. Memcached與MySQL數(shù)據(jù)庫(kù)數(shù)據(jù)一致性問(wèn)題。

          3. Memcached數(shù)據(jù)命中率低或down機(jī),大量訪問(wèn)直接穿透到DB,MySQL無(wú)法支撐。

          4. 跨機(jī)房cache同步問(wèn)題。

          眾多NoSQL百花齊放,如何選擇

          最近幾年,業(yè)界不斷涌現(xiàn)出很多各種各樣的NoSQL產(chǎn)品,那么如何才能正確地使用好這些產(chǎn)品,最大化地發(fā)揮其長(zhǎng)處,是我們需要深入研究和思考的問(wèn) 題,實(shí)際歸根結(jié)底最重要的是了解這些產(chǎn)品的定位,并且了解到每款產(chǎn)品的tradeoffs,在實(shí)際應(yīng)用中做到揚(yáng)長(zhǎng)避短,總體上這些NoSQL主要用于解決 以下幾種問(wèn)題

          1. 少量數(shù)據(jù)存儲(chǔ),高速讀寫(xiě)訪問(wèn)。此類產(chǎn)品通過(guò)數(shù)據(jù)全部in-momery 的方式來(lái)保證高速訪問(wèn),同時(shí)提供數(shù)據(jù)落地的功能,實(shí)際這正是Redis最主要的適用場(chǎng)景。

          2. 海量數(shù)據(jù)存儲(chǔ),分布式系統(tǒng)支持,數(shù)據(jù)一致性保證,方便的集群節(jié)點(diǎn)添加/刪除。

          3. 這方面最具代表性的是dynamo和bigtable 2篇論文所闡述的思路。前者是一個(gè)完全無(wú)中心的設(shè)計(jì),節(jié)點(diǎn)之間通過(guò)gossip方式傳遞集群信息,數(shù)據(jù)保證最終一致性,后者是一個(gè)中心化的方案設(shè)計(jì),通過(guò) 類似一個(gè)分布式鎖服務(wù)來(lái)保證強(qiáng)一致性,數(shù)據(jù)寫(xiě)入先寫(xiě)內(nèi)存和redo log,然后定期compat歸并到磁盤上,將隨機(jī)寫(xiě)優(yōu)化為順序?qū)懀岣邔?xiě)入性能。

          4. Schema free,auto-sharding等。比如目前常見(jiàn)的一些文檔數(shù)據(jù)庫(kù)都是支持schema-free的,直接存儲(chǔ)json格式數(shù)據(jù),并且支持auto-sharding等功能,比如mongodb。

          面對(duì)這些不同類型的NoSQL產(chǎn)品,我們需要根據(jù)我們的業(yè)務(wù)場(chǎng)景選擇最合適的產(chǎn)品。

                  

          Redis適用場(chǎng)景,如何正確的使用

          前面已經(jīng)分析過(guò),Redis最適合所有數(shù)據(jù)in-momory的場(chǎng)景,雖然Redis也提供持久化功能,但實(shí)際更多的是一個(gè)disk-backed 的功能,跟傳統(tǒng)意義上的持久化有比較大的差別,那么可能大家就會(huì)有疑問(wèn),似乎Redis更像一個(gè)加強(qiáng)版的Memcached,那么何時(shí)使用 Memcached,何時(shí)使用Redis呢?

          Redis與Memcached的比較

          1. 網(wǎng)絡(luò)IO模型

          2. Memcached是多線程,非阻塞IO復(fù)用的網(wǎng)絡(luò)模型,分為監(jiān)聽(tīng)主線程和worker子線程,監(jiān)聽(tīng)線程監(jiān)聽(tīng)網(wǎng)絡(luò)連接,接受請(qǐng)求后,將連接 描述字pipe 傳遞給worker線程,進(jìn)行讀寫(xiě)IO, 網(wǎng)絡(luò)層使用libevent封裝的事件庫(kù),多線程模型可以發(fā)揮多核作用,但是引入了cache coherency和鎖的問(wèn)題,比如,Memcached最常用的stats 命令,實(shí)際Memcached所有操作都要對(duì)這個(gè)全局變量加鎖,進(jìn)行計(jì)數(shù)等工作,帶來(lái)了性能損耗。

            (Memcached網(wǎng)絡(luò)IO模型)

            Redis使用單線程的IO復(fù)用模型,自己封裝了一個(gè)簡(jiǎn)單的AeEvent事件處理框架,主要實(shí)現(xiàn)了epoll、kqueue和 select,對(duì)于單純只有IO操作來(lái)說(shuō),單線程可以將速度優(yōu)勢(shì)發(fā)揮到最大,但是Redis也提供了一些簡(jiǎn)單的計(jì)算功能,比如排序、聚合等,對(duì)于這些操 作,單線程模型實(shí)際會(huì)嚴(yán)重影響整體吞吐量,CPU計(jì)算過(guò)程中,整個(gè)IO調(diào)度都是被阻塞住的。

          3. 內(nèi)存管理方面

          4. Memcached使用預(yù)分配的內(nèi)存池的方式,使用slab和大小不同的chunk來(lái)管理內(nèi)存,Item根據(jù)大小選擇合適的chunk存 儲(chǔ),內(nèi)存池的方式可以省去申請(qǐng)/釋放內(nèi)存的開(kāi)銷,并且能減小內(nèi)存碎片產(chǎn)生,但這種方式也會(huì)帶來(lái)一定程度上的空間浪費(fèi),并且在內(nèi)存仍然有很大空間時(shí),新的數(shù) 據(jù)也可能會(huì)被剔除,原因可以參考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/

            Redis使用現(xiàn)場(chǎng)申請(qǐng)內(nèi)存的方式來(lái)存儲(chǔ)數(shù)據(jù),并且很少使用free-list等方式來(lái)優(yōu)化內(nèi)存分配,會(huì)在一定程度上存在內(nèi)存碎 片,Redis跟據(jù)存儲(chǔ)命令參數(shù),會(huì)把帶過(guò)期時(shí)間的數(shù)據(jù)單獨(dú)存放在一起,并把它們稱為臨時(shí)數(shù)據(jù),非臨時(shí)數(shù)據(jù)是永遠(yuǎn)不會(huì)被剔除的,即便物理內(nèi)存不夠,導(dǎo)致 swap也不會(huì)剔除任何非臨時(shí)數(shù)據(jù)(但會(huì)嘗試剔除部分臨時(shí)數(shù)據(jù)),這點(diǎn)上Redis更適合作為存儲(chǔ)而不是cache。

          5. 數(shù)據(jù)一致性問(wèn)題

          6. Memcached提供了cas命令,可以保證多個(gè)并發(fā)訪問(wèn)操作同一份數(shù)據(jù)的一致性問(wèn)題。 Redis沒(méi)有提供cas 命令,并不能保證這點(diǎn),不過(guò)Redis提供了事務(wù)的功能,可以保證一串 命令的原子性,中間不會(huì)被任何操作打斷。

          7. 存儲(chǔ)方式及其它方面

          8. Memcached基本只支持簡(jiǎn)單的key-value存儲(chǔ),不支持枚舉,不支持持久化和復(fù)制等功能

            Redis除key/value之外,還支持list,set,sorted set,hash等眾多數(shù)據(jù)結(jié)構(gòu),提供了KEYS

            進(jìn)行枚舉操作,但不能在線上使用,如果需要枚舉線上數(shù)據(jù),Redis提供了工具可以直接掃描其dump文件,枚舉出所有數(shù)據(jù),Redis還同時(shí)提供了持久化和復(fù)制等功能。

          9. 關(guān)于不同語(yǔ)言的客戶端支持

          10. 在不同語(yǔ)言的客戶端方面,Memcached和Redis都有豐富的第三方客戶端可供選擇,不過(guò)因?yàn)镸emcached發(fā)展的時(shí)間更久一 些,目前看在客戶端支持方面,Memcached的很多客戶端更加成熟穩(wěn)定,而Redis由于其協(xié)議本身就比Memcached復(fù)雜,加上作者不斷增加新 的功能等,對(duì)應(yīng)第三方客戶端跟進(jìn)速度可能會(huì)趕不上,有時(shí)可能需要自己在第三方客戶端基礎(chǔ)上做些修改才能更好的使用。

          根據(jù)以上比較不難看出,當(dāng)我們不希望數(shù)據(jù)被踢出,或者需要除key/value之外的更多數(shù)據(jù)類型時(shí),或者需要落地功能時(shí),使用Redis比使用Memcached更合適。

          關(guān)于Redis的一些周邊功能

          Redis除了作為存儲(chǔ)之外還提供了一些其它方面的功能,比如聚合計(jì)算、pubsub、scripting等,對(duì)于此類功能需要了解其實(shí)現(xiàn)原理,清 楚地了解到它的局限性后,才能正確的使用,比如pubsub功能,這個(gè)實(shí)際是沒(méi)有任何持久化支持的,消費(fèi)方連接閃斷或重連之間過(guò)來(lái)的消息是會(huì)全部丟失的, 又比如聚合計(jì)算和scripting等功能受Redis單線程模型所限,是不可能達(dá)到很高的吞吐量的,需要謹(jǐn)慎使用。

          總的來(lái)說(shuō)Redis作者是一位非常勤奮的開(kāi)發(fā)者,可以經(jīng)常看到作者在嘗試著各種不同的新鮮想法和思路,針對(duì)這些方面的功能就要求我們需要深入了解后再使用。

          總結(jié):

          1. Redis使用最佳方式是全部數(shù)據(jù)in-memory。

          2. Redis更多場(chǎng)景是作為Memcached的替代者來(lái)使用。

          3. 當(dāng)需要除key/value之外的更多數(shù)據(jù)類型支持時(shí),使用Redis更合適。

          4. 當(dāng)存儲(chǔ)的數(shù)據(jù)不能被剔除時(shí),使用Redis更合適。

          后續(xù)關(guān)于Redis文章計(jì)劃:

          1. Redis數(shù)據(jù)類型與容量規(guī)劃。

          2. 如何根據(jù)業(yè)務(wù)場(chǎng)景搭建穩(wěn)定,可靠,可擴(kuò)展的Redis集群。

          3. Redis參數(shù),代碼優(yōu)化及二次開(kāi)發(fā)基礎(chǔ)實(shí)踐。

          關(guān)于作者

          田琪,目前負(fù)責(zé)新浪微博平臺(tái)底層架構(gòu)與研發(fā)工作,之前曾擔(dān)任搜狐白社會(huì)實(shí)時(shí)游戲平臺(tái)核心架構(gòu)工作,主要關(guān)注webgame, 分布式存儲(chǔ),nosql 和 erlang 等領(lǐng)域,目前主要從事mysql源代碼的一些深入研究工作,浪微博:http://weibo.com/bachmozart

          posted on 2014-08-26 09:04 paulwong 閱讀(456) 評(píng)論(0)  編輯  收藏 所屬分類: REDIS

          主站蜘蛛池模板: 和平区| 夹江县| 上杭县| 离岛区| 大宁县| 四川省| 富阳市| 潼关县| 肇东市| 绥化市| 永城市| 横峰县| 乐陵市| 炎陵县| 灌阳县| 兴仁县| 九龙县| 永仁县| 资阳市| 阳新县| 永和县| 延边| 赤水市| 成都市| 石台县| 基隆市| 钟山县| 和顺县| 泸定县| 朝阳市| 丽江市| 河津市| 乐昌市| 资讯 | 防城港市| 增城市| 平定县| 瑞昌市| 涟源市| 深州市| 扎赉特旗|