學習Redis(二)

 

自關係型DB誕生40年來,從理論產生到現實產品(MySQLOracle),已在DB領域上升到了霸主地位,每一年數百億$的龐大產業市場;php

隨着web2.0的興起,對於規模日益龐大的海量數據,傳統的關係型DB顯得力不從心,如超大規模和高併發的微博、微信、SNSsocail network sitesocail network services)純動態網站等,關係型DB面臨不少難以克服的問題,有IO瓶頸、性能瓶頸都難以有效突破,因而出現了不少針對特定場景,以高性能和使用便利爲目的的差別化的DB產品——NOSQLnot only SQL,非關係型類的DB),如:專一於key-value查詢的redismemcachedttserver,面向文檔的mongoDB,面向列的hbase、cassandra,面向圖的neo4j,這些nosql的共同特色是:去除一切和高性能無關的功能,追求高併發、高性能,在擴展上支持集羣和分佈式;html

NOSQLnot only sql,而不是no sql,並沒徹底否認關係型DB,而是做爲傳統關係型DB的一個補充,在特定的場景下可發揮出不可思議的高效率和高性能;前端

 

facebook360使用cassandra來存儲海量社交數據;twitter在其url抓取系統裏綜合運用了assandramemcachedgoogle使用了bigtableamazon使用dynamosina微博使用redismemcached來提升高併發性能;taobao使用hbase並在其基礎上研發了本身的oceanbasedouban也有本身的nosql產品beansDBnode

mongoDB被普遍用於存儲非結構化數據,中小企業對於常規內容的存儲也有用mongoDB;在電信運營商的分析項目中,使用hbase承載從switch上採集高速數據流;python

 

熟知nosql的原理和每種產品的特性和使用場景,用以進行技術選型,實施、管理集羣,是系統管理者、DBA、架構師要掌握的知識;linux

 

使用nosqlgit

high performance,對DB高併發rw的需求(web2.0網站要根據用戶個性化信息來實時生成動態頁面和提供動態信息,因此難以使用動態頁面靜態化技術,所以對DB的併發和負載要求很是高,每每要達到每秒上萬次rw,關係型DB包括分佈式集羣應付上萬次查詢(r)還勉強頂得住,但若應付上萬次SQLw操做,物理硬盤IO已沒法承受,對於普通大型BBS網站,存在高併發w的需求);github

huge storage,海量數據的高效率存儲和訪問需求(對於大型SNS,天天用戶產生海量的動態數據,如friendfeed一個月有2.5億條用戶動態,對於關係型DB若要在一張2.5億條記錄的表中進行SQL查詢,效率極其低下;大型web網站的用戶登陸系統,如tencentshengda等數以億計的帳號,關係型DB難以應付);web

high scalability & high availability,高擴展性和高可用需求(在互聯網網站架構中,DB是最難橫向擴展的,在應用系統的用戶量和訪問量與日俱增時,DB很難像web serverapp server那樣簡單的經過添加硬件node來擴展性能和負載能力,對不少需提供24h不間斷業務的網站來講,對DB進行升級和擴展很是痛苦,每每要停機維護和數據遷移);redis

 

nosql將關係型DB的如下特性去除:

關係型DB數據事務一致性需求(傳統關係型DB要保持DB事務一致性需求,從而沒法知足高併發rw的需求);

DBr實時性和w實時性需求(對關係型DB插入一條數據以後當即查詢,可查出來,但對不少web應用來講,並不要求這麼高的實時性);

對複雜的SQL查詢,特別是多表關聯查詢需求(任何大數據量的web系統,尤爲是SNS,很是忌諱多個大表的關聯查詢,和複雜的數據分析類型SQL查詢,從需求和產品設計角度,避免這種狀況發生,每每更多的是單表的主鍵查詢,及單表的簡單條件分頁查詢,SQL的功能被極大的弱化);

 

nosql適用狀況(數據模型比較簡單;須要靈活更強的IT系統;對DB性能要求較高;不須要高度的數據一致性;對於給定的key,較容易映射覆雜value的環境);

 

 

nosql主流軟件分類及特色:

1key-value存儲,key-value systems basically support getputand delete operations based on a primary key,相似傳統語言中的hash表,可經過key來添加、查詢、刪除數據,由於使用主鍵訪問,因此會有不錯的性能及擴展性;key-value DB主要是使用一個hash表,此表中有一個特定的key和一個指針指向特定的數據,key-value模型對於IT系統的優點在於簡單、易部署;

產品有:redismemcachedBDBberkeley DB)memcacheDBttserver(tokyo cabinet/tokyo tyrant)riakamazon'sdynamoproject voldemort

典型應用:內容緩存、適合混合工做負載並擴展大的數據集;

數據模型:一系統key:value對,僅能經過key查詢value

優點:快速查詢;劣勢:存儲的數據缺乏結構化;

適用場景:存儲用戶信息,如會話、配置文件、參數、購物車、計數(統計粉絲關注)等,這些信息通常和IDkey)掛鉤;

不適用場景:不能經過value查詢key;不能存儲數據之間的關係(不能經過兩個或更多的key來關聯數據);不支持事務,有故障時不能回滾;

企業應用:twitterredis&memcached),stackoverflowredis),instagramredis),youtubememcached),wikipediamemcached),sinaredis),baidumemcached),baikettserver

2column-oriented列存儲,column-oriented systems still use tables but have no joins(joins must be handled within your application).obviously,they store data by column as a opposed to traditional row-oriented database.this makes aggregations much easier.column-oriented存儲DB將數據存儲在列族column family中,一個column family存儲常常被一塊兒查詢的相關數據;例如一個person類,一般會一塊兒查詢nameage而不是salarynameage會在一個comumn family中,而salary在另外一個column family中;一般用來應付分佈式存儲的海量數據,key仍存在,只不過是指向了多個column,這些columncolumn family來安排;

產品有:cassandrahbaseriak

典型應用:分佈式FS

數據模型:以column family式存儲,將同一列數據存到一塊兒;

優點:查找速度快,可擴展性強,尤爲在分佈式擴展方面;劣勢:功能相對侷限;

適用場景:日誌(每一個application可將信息寫入本身的column family中);blog平臺(存儲每一個信息到不一樣的column family中,如標籤、類別、文章等);

不適用場景:不支持事務;不支持原型設計,一旦查詢方式改變,必須從新設計column family

企業應用:githubriak),bestbuyriak),ebaycassandra),instagramcassandra),nasacassandra),twittercassandra&hbase),facebookhbase),yahoohbase),taobaohbase),360cassandra

3document-oriented存儲,document-orientedsystems store structured "documents" such as JSON or XML but have nojoins(joins must be handled within your application).it's very easy to map datafrom object-oriented software to these systems.,文檔DB來自lotus notes辦公軟件,與key-value存儲相似,可看做是key-valueDB的升級版,容許嵌套key-valuedocument-oriented DBkey-value DB查詢效率要高,document-oriented的數據模型是版本化的文檔、半結構化的文檔以特定的格式存儲,如jsondocument-oriented DB將數據以文檔形式存儲,每一個文檔都是自包含的數據單元,是一系列數據項的集合,每一個數據項都有一個名稱與對應的值,值能夠是簡單的數據類型(stringnumberdate等),也能夠是複雜的數據類型(sequence tablerelated object),數據存儲的最小單位是文檔,同一個表中存儲的文檔屬性能夠是不一樣的,數據可用xmljsonbson等多種形式存儲;

產品有:mongoDBravenDBcouchDB

典型應用:web應用;

數據模型:一系列key:value對;

優點:數據結構要求不嚴格;劣勢:查詢性能不高,缺少統一的查詢語法;

適用場景:日誌(每一個應用程序有不一樣的日誌信息);document-oriented DB無固定的模式,可用來存儲不一樣的信息;分析(鑑於它的弱模式結構,不改變模式就可存儲不一樣的度量方法及添加新的度量);

不適用場景:不支持在不一樣的文檔上添加事務(不支持文檔間的事務);

企業應用:SAPmongoDB),codecademymongoDB),foursquaremongoDB),nbc newsravenDB

4graph存儲,數據以圖的方式存儲,實體做爲頂點,實體之間的關係做爲邊,若有3個實體,steve jobsapplenext,則會有2founded by邊,將applenext鏈接到steve jobs;圖形結構的DB同行列及剛性結構的SQL DB不一樣,它是使用靈活的圖形模型,並能擴展到多個server上,nosql DB沒有標準的查詢語言SQL,在進行DB查詢須要制定數據模型,許多nosql DBREST式的數據接口或查詢API

產品有:neo4jinfogridinfinite graphorientDB

典型應用:SNS、推薦系統等,專一於構建關係圖譜;

數據模型:圖結構;

優點:利用圖結構相關算法;劣勢:須要對整個圖做計算才能得出結果,不容易作分佈式的集羣方案;

適用場景:在關係型強的數據中;推薦引擎,若將數據以圖的形式表現,會很是有益於推薦的制定;

不適用場景:數據模型適用範圍小,不多有操做涉及到整個圖;

企業應用:adobeciscot-mobile均使用neo4j

 

 

memcached

http://memcached.org/

key-value,是一個開源的高性能的,具備分佈式內存對象的緩存系統,經過它能夠減輕DB負載,加速動態web應用,最初始版本在2003年開發完成,不少公司都使用它來構建本身的大負載網站或提升網站響應速度,項目名稱memcache,主程序文件爲memcached

緩存通常用來保存一些常常被存取的對象或數據,經過內存來存取對象或數據要比disk快不少,memcached是一種內存緩存(進程退出,數據將丟失),把常常存取的對象或數據緩存在內存中,內存中緩存的這些數據經過API的方式被存取,數據就像一張大的hash表,以key:value對的方式存在,memcached經過緩存常常被存取的對象或數據,減輕DB的壓力,提升網站的響應速度,構建出速度更快的可擴展的web應用;

memcached是內存緩存,緩存的數據不能持久化,若memcached在下次剛啓動,因爲內存中尚未緩存的數據,若在這一時間段請求DB的量不少,會形成DB壓力過大,解決:經過腳本或程序,從DB裏把數據r出來,先存到memcached中,再容許前端訪問;

特色(部署簡單,支持高併發、高性能;經過程序或LB可實現分佈式;緩存的數據在內存中,重啓服務後內容丟失);

 

memcacheDB

http://memcachedb.org/

sina基於memcached開發的一個開源項目,經過爲memcached增長BDB的持久化存儲機制和異步master-slave複製機制,使memcached具有事務恢復能力、持久化能力和分佈式複製能力,適合超高性能rw速度、持久化保存的應用場景,sina用在blog上,若對memcached有持久化需求可考慮使用memcacheDB

memcacheDB支持相似MySQLmaster-slave同步(rw-splittingmaster可讀寫,slave只讀);

特色(high performance r/w for a key-value based object;high reliablepersistent storage with transaction; high availability data storage withreplication; memcache protocol compatibility);

 

ttservertokyo tyrant/tokyocabinet):

tokyo cabinet是日本人mikio hirabayashi開發的一款DBM數據庫,該DBrw很是快,是BDB的幾倍,哈希模式寫入100萬條數據只需0.643s,讀100萬條數據只需0.773s

tokyo tyrant是提供tokyo cabinet數據庫的網絡接口,它使用簡單的基於tcp/ip二進制協議進行通訊,同時它擁有memcached的兼容協議,還可用http/1.1協議進行數據轉換,實現了跨平臺、跨語言使用,tokyo tyrant採用熱備份、更新日誌記錄、replication來實現HA和高可靠性,tokyo tyrant可運行在linuxfreeBSDmacsolaristokyo tyrant is written in the C language,and provided as API ofC,Perl,and ruby,tokyo tyrant is available on platforms which have APIconforming to C99 and POSIX,tokyo tyrant is a free software licensed under theGNU lesser general public license

tokyo cabinet + tokyo tyrant構成了一款支持高併發的分佈式持久存儲系統,支持故障轉移、高併發的分佈式key-value持久存儲系統,查詢速度快、存放數據量大、支持高併發、很是適合主鍵進行查詢,但不能進行復雜的條件查詢;對任何原有memcached客戶端來說,可將tokyo tyrant當作是一個memcached,惟一不一樣的是它可持久存儲

優點(不但支持內存緩存還可持久化存儲;故障轉移,tokyo tyrant支持主從模式,也支持雙機互爲主從模式,主從庫都可rw5KW條數據級別內的訪問至關快;兼容memcached協議,客戶端不需更改任何代碼);

 

mongoDBdocument-oriented):

MongoDB是一個基於分佈式文件存儲的數據庫。由C++語言編寫。旨在爲WEB應用提供可擴展的高性能數據存儲解決方案。

MongoDB是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。他支持的數據結構很是鬆散,是相似jsonbson格式,所以能夠存儲比較複雜的數據類型。Mongo最大的特色是他支持的查詢語言很是強大,其語法有點相似於面向對象的查詢語言,幾乎能夠實現相似關係數據庫單表查詢的絕大部分功能,並且還支持對數據創建索引。

特色(易部署、高性能、易使用、存儲數據很是方便);

主要功能特性有:

面向集合存儲,易存儲對象類型的數據(所謂「面向集合」(Collection-Oriented),意思是數據被分組存儲在數據集中,被稱爲一個集合(Collection)。每一個集合在數據庫中都有一個惟一的標識名,而且能夠包含無限數目的文檔。集合的概念相似關係型數據庫(RDBMS)裏的表(table),不一樣的是它不須要定義任何模式(schema)Nytro MegaRAID技術中的閃存高速緩存算法,可以快速識別數據庫內大數據集中的熱數據,提供一致的性能改進。)

模式自由(schema-free,意味着對於存儲在mongodb數據庫中的文件,咱們不須要知道它的任何結構定義。若是須要的話,你徹底能夠把不一樣結構的文件存儲在同一個數據庫裏。)

支持動態查詢。

支持徹底索引,包含內部對象。

支持查詢。

支持複製和故障恢復。

使用高效的二進制數據存儲,包括大型對象(如視頻等)。

自動處理碎片,以支持雲計算層次的擴展性。

支持RUBYPYTHONJAVAC++PHPC#等多種語言。

文件存儲格式爲BSON(一種JSON的擴展)(存儲在集合中的文檔,被存儲爲鍵-值對的形式。鍵用於惟一標識一個文檔,爲字符串類型,而值則能夠是各類複雜的文件類型。咱們稱這種存儲形式爲BSONBinary Serialized Document Format)

可經過網絡訪問(mongoDBserver-side可運行在linuxwinOS X平臺,最好64bit,默認port27017

mongoDB把數據存儲在文件中,默認在/data/db,爲提升效率使用內存映射對文件進行管理;

 

cassandracolumn-oriented):

Cassandra是一套開源分佈式NoSQL數據庫系統。它最初由Facebook開發,用於儲存收件箱等簡單格式數據,集GoogleBigTable的數據模型與Amazon Dynamo的徹底分佈式的架構於一身Facebook2008 Cassandra 開源,此後,因爲Cassandra良好的可擴展性,被DiggTwitter等知名Web 2.0網站所採納,成爲了一種流行的分佈式結構化數據存儲方案。

Cassandra是一個混合型的非關係的數據庫,相似於GoogleBigTable。其主要功能比Dynamo(分佈式的Key-Value存儲系統)更豐富,但支持度卻不如文檔存儲MongoDB(介於關係數據庫和非關係數據庫之間的開源產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。支持的數據結構很是鬆散,是相似jsonbjson格式,所以能夠存儲比較複雜的數據類型)。Cassandra最初由Facebook開發,後轉變成了開源項目。它是一個網絡社交雲計算方面理想的數據庫。以Amazon專有的徹底分佈式的Dynamo爲基礎,結合了Google BigTable基於列族(Column Family)的數據模型。P2P去中心化的存儲。不少方面均可以稱之爲Dynamo 2.0

Cassandra的主要特色就是它不是一個數據庫,而是由一堆數據庫節點共同構成的一個分佈式網絡服務,對Cassandra 的一個寫操做,會被複制到其餘節點上去,對Cassandra的讀操做,也會被路由到某個節點上面去讀取。對於一個Cassandra羣集來講,擴展性能是比較簡單的事情,只管在羣集裏面添加節點就能夠了。

主要特性(分佈式、基於cloumn的結構化、高伸展性)

 

 

生產環境選擇:

常規cache應用,memcached最合適,簡單、易用、高效;很差的是僅在內存緩存,大數據量要先預熱再提供服務,沒法直接實現master-salve同步;

若要持久化存儲,用memcacheDBttserver,好處是兼容memcached協議,還能實現master-salve同步(生產中如有2KW條之內的數據量,用ttserver替代memcached最合適);

生產中有大數據量,可用redis持久化存儲替代memcached,很差的是要重寫代碼(不兼容memcached協議);

生產中有PB級海量數據,且有不少server,延時和響應在必定時間內可接受,用cassandrahbasemongoDB均可勝任;

 

 

rediskey-value):

redis is an opensource,BSD liscensed,advanced key-value store,it is often referred to as a data structure server since keys can contain string,hashes,lists,sets and sorted sets.

REmote DIctionary server是一個開源的使用ANSIC語言編寫(代碼3W多行)、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API;從2010315日起,Redis的開發工做由VMware主持,從20135月開始,Redis的開發由Pivotal贊助;

redis是一個key-value存儲系統;和Memcached相似,它支持存儲的value類型相對更多,5種:string(字符串)list(列表)set(集合)zset(sorted set--有序集合)hash(哈希類型);

這些數據類型都支持push/popadd/remove及取交集並集和差集及更豐富的操做,並且這些操做都是原子性的,在此基礎上,redis支持各類不一樣方式的排序;

memcached同樣,爲了保證效率,數據都是緩存在內存中,區別的是redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件,而且在此基礎上實現了master-slave同步;

redis 是一個高性能的key-value數據庫,redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部分場合能夠對關係數據庫起到很好的補充做用;

它提供了JavaC/C++C#PHPJavaScriptPerlObject-CPythonRubyErlang等客戶端,使用很方便;

redis支持master-slave同步。數據能夠從主服務器向任意數量的從服務器上同步,從服務器能夠是關聯其餘從服務器的主服務器,這使得Redis可執行單層樹複製,存盤能夠有意無心的對數據進行寫操做,因爲徹底實現了PUB/SUB機制,使得從數據庫在任何地方同步樹時,可訂閱一個頻道並接收主服務器完整的消息發佈記錄,同步對讀取操做的可擴展性和數據冗餘頗有幫助;

redis的官網地址是redis.io。(域名後綴io屬於國家域名,是british Indian Ocean territory,即英屬印度洋領地)

特色(key-value類型存儲;內存緩存(同memcached);可持久化(同memcacheDBttserver),支持數據可靠存儲及落;數據類型更豐富;支持集羣、分佈式;單進程、單線程高性能server(可多實例運行);crash safe & recovery slow;單機qps可達到10Wquery per second;適合小數據量高速rw);

若從memcached改成-->redis客戶代碼要改;

優點(可持久化存儲數據;性能很高,支持超10W/srw頻率;豐富的數據類型;redis的全部操做都是原子性的,還支持幾個操做合併後的原子性支持;豐富的特性,支持publisher/subscriber、通知、key過時等特性;支持異機主從複製);

劣勢(系統運行有毛刺;不一樣命令延遲差異大;內存管理開銷大(不要超過物理內存的60%);buffer io形成系統OOM);

 

 

redis持久化(兩種:snapshottingaof):

一般redis將數據存儲於內存中(或被配置使用虛擬內存,效率不高通常不用),經過兩種方式可實現數據持久化(snapshot默認和aofappend only file));

snapshotting是在必定間隔時間作一次持久化,若redis意外掛掉則會丟失最後一次快照的全部修改,若是應用要求嚴格不能丟失任何數據,要採用aof方式;

更新頻繁一致性要求較高,用AOF策略;更新不頻繁,可容忍少許數據丟失或錯誤,用snapshot策略;

 

使用snapshot方式,將內存中的數據以快照方式不斷寫入到二進制文件中,默認文件名dump.rdb,此種方式性能較高,可能會引發必定程序的數據丟失,可配置自動作快照持久化,例如可配置在n秒內若超過mkey被修改就自動做快照;

[root@server1 ~]# vim /etc/redis.conf

################################SNAPSHOTTING ################################

#  save <seconds> <changes>

save 900 1  #(在900s內若超過1key被修改,則觸發快照保存)

save 300 10   #(在300s內若超過10key被修改,則發起快照保存)

save 60 10000

dbfilename dump.rdb

dir /var/lib/redis/6379/

詳細過程:

redis調用fork產生子進程;

父進程繼續處理client請求,子進程負責將內存內容寫入到臨時文件,因爲oscowcopy on write寫時複製機制),父進程和子進程會共享相同的物理頁面,當父進程處理w請求時os會爲父進程要修改的頁面建立副本,而不是寫入共享的頁面,因此子進程地址空間內的數據是fork這一時刻對整個DB的一個快照;

當子進程將快照寫入臨時文件完畢後,用臨時文件替換原來的快照文件,而後子進程退出;

注:client也可以使用savebgsave通知redis server作一次快照持久化,save操做是在主線程中運行的,而redis是用一個主線程來處理全部client的請求,因此在執行save操做時會阻塞當前client的全部請求,不推薦使用,最好用bgsave

每次快照持久化都是將內存數據完整寫入到磁盤一次,並非增量的只同步變動的數據,若是數據量大且寫操做不少,會引發大量的disk io,將嚴重影響性能;數據快照的原理是將整個內存中redis的數據遍歷一遍再放到dump.rdb二進制數據文件中;

[root@server1 ~]# ll --full-time /var/lib/redis/6379/

total 4

-rw-r--r--. 1 root root 33 2016-09-18 03:32:38.887828894 -0700 dump.rdb

[root@server1 ~]# redis-cli

127.0.0.1:6379> keys *

1) "key1"

127.0.0.1:6379> set key2 value2

OK

127.0.0.1:6379> bgsave

8790:M 18 Sep 18:20:31.200 * Background saving started by pid 8794

Background saving started

127.0.0.1:6379> 8794:C 18 Sep18:20:31.204 * DB saved on disk

                                                            8794:C 18 Sep 18:20:31.204 * RDB: 0 MB of memory used by copy-on-write

                                                                                                                                  8790:M 18 Sep 18:20:31.229 * Background saving terminated with success

127.0.0.1:6379> quit

[root@server1 ~]# ll --full-time /var/lib/redis/6379/

total 4

-rw-r--r--. 1 root root 46 2016-09-18 18:20:31.199696228 -0700 dump.rdb

 

aofappend only fileredis會將收到的寫命令都經過write函數追加到文件中,默認是appendonly.aof,當redis重啓時會從新加載這個文件,用以在內存中重建整個DB

相似MySQLbinlog日誌方式,記錄每次對DB有變化的操做

aof不用於master-slave同步;

os會在kernel中緩存write作的修改,cow機制不會當即同步到disk上,可經過appendfsyncalways強制os寫入到disk,性能會受影響,但不會丟數據保證了徹底的持久化;appendfsync默認everysec,在性能和持久化方面作了折衷;appendfsync no,徹底按os來,性能最好,可能會丟數據;

[root@server1 ~]# vim /etc/redis.conf

save ""

############################## APPEND ONLYMODE ###############################

appendonly yes

appendfilename "appendonly.aof"

appendfsync everysec

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb   #(當appendonly.aof100%達到64m時會自動調用bgrewriteaof命令將此文件中重複的多餘的記錄壓縮)

[root@server1 ~]# ll --full-time /var/lib/redis/6379/

total 4

-rw-r--r--. 1 root root  0 2016-09-1818:48:29.121048063 -0700 appendonly.aof

-rw-r--r--. 1 root root 46 2016-09-1818:48:18.501048935 -0700 dump.rdb

[root@server1 ~]# redis-cli

127.0.0.1:6379> flushall

OK

127.0.0.1:6379> set num 8

OK

127.0.0.1:6379>incr num

(integer) 9

127.0.0.1:6379>incr num

(integer) 10

127.0.0.1:6379> quit

[root@server1 ~]# ll --full-time /var/lib/redis/6379

total 8

-rw-r--r--. 1 root root 116 2016-09-18 18:50:03.100611728 -0700 appendonly.aof

-rw-r--r--. 1 root root  46 2016-09-18 18:48:18.501048935 -0700dump.rdb

[root@server1 ~]# cat /var/lib/redis/6379/appendonly.aof   #redis重啓時會加載此文件中內容,如果刪除操做,可編輯此文件將del語句刪除,重啓便可恢復誤刪操做)

*2

$6

SELECT

$1

0

*1

$8

flushall

*3

$3

set

$3

num

$1

8

*2

$4

incr

$3

num

*2

$4

incr

$3

num

[root@server1 ~]# redis-cli

127.0.0.1:6379>incr num

(integer) 11

127.0.0.1:6379> get num

"11"

127.0.0.1:6379> bgrewriteaof

8826:M 18 Sep 18:54:29.263 * Backgroundappend only file rewriting started by pid 8841

Background append only file rewritingstarted

127.0.0.1:6379> 8826:M 18 Sep18:54:29.324 * AOF rewrite child asks to stop sending diffs.

                                                                                         8841:C18 Sep 18:54:29.324 * Parent agreed to stop sending diffs. Finalizing AOF...

                                        8841:C18 Sep 18:54:29.324 * Concatenating 0.00 MB of AOF diff received from parent.

                                                                                                                           8841:C 18 Sep 18:54:29.325 * SYNC append only file rewrite performed

                                                           8841:C 18 Sep18:54:29.325 * AOF rewrite: 0 MB of memory used by copy-on-write

   8826:M 18 Sep 18:54:29.396 * Background AOF rewrite terminated withsuccess

                                                                              8826:M 18 Sep18:54:29.396 * Residual parent diff successfully flushed to the rewritten AOF(0.00 MB)

                                              8826:M 18 Sep 18:54:29.396 * Background AOF rewrite finishedsuccessfully

127.0.0.1:6379> quit

[root@server1 ~]# cat /var/lib/redis/6379/appendonly.aof   #(比較先後appendonly.aof的變化)

*2

$6

SELECT

$1

0

*3

$3

SET

$3

num

$2

11

 

 

redis應用sina案例:

application-->redis

application-->redis-->MySQL   #redis做緩存用)

二次開發實現MySQLredis互相同步(MySQL-->redis(經過BRB解析binlog同步到redisredis提供特定數據結構的讀;實現關係型數據轉變成隊列數據);redis-->MySQLredis提供特定數據結構的rw;經過replication接口同時寫入到MySQL);

 

redis生產經驗:

要進行master-slave同步配置,在故障時可切換;

w數據量很大,可在master上禁用持久化,只在slave上配置數據持久化,並在master上禁止redis故障自重啓或開機自啓動;官方強烈建議master要開啓持久化,不然服務重啓將把內存空數據傳給slave

確保內存可用(物理內存通常64G-128G,磁盤最好用SSD),若內存不足時(物理內存+虛擬內存),執行dump時會無響應甚至server掛掉;

redis進程若佔總內存的60%時性能會下降(內存碎片大),儘可能不用swap

當達到最大內存時,會清空帶有過時時間的key,甚至key未達到過時時間也會清掉;

redisDB同步,要先寫DB再寫redis

 

key/value

rediskey是二進制安全的,可用任何二進制序列做爲key,例如「test」簡單的string,或jpg文件的內容均可以,空字符串也是有效的key

key規則(不要用太長的key,如1024byte,不只消耗內存,並且在數據查找時計算成本很高;也不要用過短的key,儘可能見明知義,例如用「user:1000:password」取代「u:1000:pwd」,前者更易閱讀,由此增長的空間相對於key objectvalue object很小可忽略;最好堅持用一種模式,例如「object-type:id:field」,「comment:1234:reply.to」,多個單詞用點隔開);

key建議(長度10-20,例如object-type:id:field);

vlaue建議(string不超過2000setsorted set不超過5000);

根據內容長度及佔用的內存空間規劃,若數據量很大,使用不一樣的instance

#redis-cli set user:test01:passwd test01

#redis-cli get user:test01:passwd

 

wKiom1ffeIiiXA8oAABJIvx_ifo940.jpg

 

redis測試:

[root@server1 ~]# redis-benchmark -h 10.96.20.113 -p 6379 -c 10 -n 1000

 

 

redis優化:

1)內存管理優化:

redis hashvalue內部是一個hash map,若該map的成員數較少,則會採用相似一堆線性緊湊格式來存儲該map,即省去了大量指針的內存開銷;

相關參數:

hash-max-zipmap-entries 64指當value這個map內部不超過多少個成員時會採用線性緊湊技術,默認64,即value內部有少於64個成員時使用線性緊湊格式存儲,超過該值自動轉爲hash map方式;

hash-max-zipmap-value 512指當value這個map內的每一個成員值長度不超過多少個byte就會採用線性緊湊格式存儲來節省空間;

以上兩個條件任意一個知足都會轉爲真正的hash map,將再也不節省內存,這兩個參數值不是越大越好,hash map的優點是查找和操做的時間複雜度都是O1),而線性緊湊格式存儲則是On),若是成員不多則影響不大,不然會嚴重影響性能,要權衡好這兩個參數值,整體上根本的是權衡時間成本和空間成本;

2)內存預分配:

memcached相比redis內部沒有在內存分配方面作過多優化,在必定程度上會存在內存碎片,不過大多數狀況下這不會成爲redis的性能瓶頸,若是在redis中存儲的大部分數據是數值型的話,redis內部採用了shared integer方式來省去分配內存的開銷,即在redis啓動時先分配一個從1-10000的數值放在一個pool中,若是存儲的數值剛好是默認範圍內的,則直接從pool中取出該對象,並經過引用計數的方式共享,這樣在redis中若存儲了大量數值也能在必定程度上節省內存並提升性能,pool的範圍在源碼中定義REDIS_SHARED_INTEGERS默認10000,修改後要從新編譯;

3)持久化機制:

snapshotredis內部的一個定時器事件,每隔固定時間去檢查當前數據發生的改變次數與時間是否知足配置的持久化觸發條件,若是知足則經過os fork建立一個子進程,這個子進程默認會與父進程共享相同的內存地址空間,這時可經過子進程來遍歷整個內存,進而再進行存儲操做,而主進程仍可提供服務,當有寫入時由os按內存頁page爲單位進行cow保證父進程與子進程之間不相互影響,缺點:定時快照只表明一段時間的內存對象,redis重啓後會丟失上次快照與出故障時這個時間段的數據;

aof記錄使redis內存數據發生改變的命令,保存在appendonly.aof中,相似MySQLbinlog,但又有不一樣,redis利用backlog同步數據,缺點:appendonly.aof會愈來愈大,多達幾十G,重啓redis恢復時會用稍長時間,這個耗時不是由於disk讀取速度慢,而主要是讀出的全部命令都要在內存中執行一遍,要保證全部數據都不丟失使用appendfsync always,這會帶來整個系統性能降低,若數據量很大可考慮將數據保存到不一樣的redis instance中,這樣既可減小緩存失效帶來的影響,又可加快數據恢復的速度;

持久化崩潰問題(通常redis佔總內存60%時會出現不穩定或崩潰,redis使用物理內存較多,在還沒超過實際物理內存總容量時就出現不穩定甚至崩潰,有人認爲是基於snapshot方式持久化時,fork系統調用形成內存佔用加倍致使,不徹底準確,fork調用的cow機制是基於os內存page這個單位的,只有寫入dirty page會被複制,但redis系統不會在短期內全部頁都發生了寫入而致使複製;redis持久化使用了buffer io形成崩潰,buffer io是指redis對持久化文件的寫入和讀取操做都會使用物理內存的page cache,而大多數DB系統會使用direct io來繞過這層page cache並自行維護一個數據的cache,當redis持久化的文件過大(尤爲是快照文件),並對其進行rw時,disk文件中的數據都會被加載到物理內存中做爲os對該文件的一層cache,而這層cache的數據與redis內存中管理的數據是重複的,雖然kernel在物理內存緊張時會作page cache的剔除工做,但kernel極可能認爲某塊page cache很重要,而讓進程swap,這時redis就開始不穩定或崩潰了);

redis優化總結:

根據業務須要選擇合適的數據類型,併爲不一樣的應用場景設置相應的緊湊存儲參數;

當業務場景不須要數據持久化時,關閉全部的持久化方式可得到最佳的性能和最大的內存使用量;

若須要使用持久化,根據是否能夠容忍重啓後丟失部分數據,在snapshotaof,這二者中選其一,不要使用虛擬內存vmdisk store方式(diskstoreobsolete);

儘可能不要讓redis超過佔總內存的60%

redis.confmaxmemory,是告訴redis當使用了多少物理內存後就開始拒絕後續的寫入請求,該參數能很好的保護redis不會由於使用了過多的物理內存而致使swap,最終嚴重影響性能開始不穩定甚至崩潰;

大數據量儘可能按業務使用多個redis instance把數據分散開;

開發優化(一次性成批量寫入(如50w條記錄使用hmset須要0.04278秒)比屢次循環寫入(50w條記錄寫入須要0.87767秒)效率要高,可適當考慮延遲彙總寫入,分佈式的redis系統一次性寫入只需耗費數據傳輸的速度(創建鏈接、傳輸數據、關閉鏈接),寫入速度太快可忽略;設計數據結構時儘可能少佔內存,如keycoupon:exterprise:N:consumer:N改成cp:et:N:cm:N;命名方式除了簡短,可用後綴s表明set,後綴l表明list,後綴單數則表明統計數據等自定義方法;hash結構存儲使用了zipmap會大大壓縮數據,50w條記錄用string方式大約45m,而使用hash存儲下降到不到20m空間,hash設計參數採用了instagram的設計,如50w條數據分紅500hash bucket,每一個裏面存1000個;use hashes when possible

 

 

 

操做:

master10.96.20.113,主機名server1

slave10.96.20.114,主機名server2

http://download.redis.io/releases/redis-3.0.7.tar.gz

 

[root@server1 ~]# uname -rm

2.6.32-431.el6.x86_64 x86_64

[root@server1 ~]# cat /etc/redhat-release

Red Hat Enterprise Linux Server release 6.5(Santiago)

 

[root@server1 ~]# tar xf redis-3.0.7.tar.gz

[root@server1 ~]# cd redis-3.0.7

[root@server1 redis-3.0.7]# less README

[root@server1 redis-3.0.7]# make

[root@server1 redis-3.0.7]# make PREFIX=/usr/local/redis install

 

[root@server1 redis-3.0.7]# ls/usr/local/redis/bin   #redis-serverredisdaemon程序);redis-cliredis命令行操做工具,也可用telnet根據純文本協議操做);redis-benchmarkredis性能測試工具,測試rw性能);redis-check-aof(對更新日誌appendonly.aof檢查,相似檢查MySQLbinlog的工具);redis-check-dump(用於本地數據庫rdb文件的檢查))

redis-benchmark  redis-check-aof  redis-check-dump  redis-cli redis-sentinel  redis-server

[root@server1 redis-3.0.7]# vim /etc/profile.d/redis.sh

export PATH=$PATH:/usr/local/redis/bin/

[root@server1 redis-3.0.7]# . !$

. /etc/profile.d/redis.sh

[root@server1 redis-3.0.7]# whichredis-server

/usr/local/redis/bin/redis-server

[root@server1 redis-3.0.7]# cp redis.conf /etc/

[root@server1 redis-3.0.7]# egrep -v "^#|^$" /etc/redis.conf   #redis.conf文件中分段配置,有:includesgeneralsnapshottingreplicationsecuritylimitsappend onlymodelua scriptingredis clusterslow loglatency monitorevent notificationadvanced config

daemonize no

pidfile /var/run/redis.pid

port 6379

tcp-backlog 511   #tcp隊列,/proc/sys/net/core/somaxconn/proc/sys/net/ipv4/tcp_max_syn_backlog

timeout 0   #client超時,0表示不超時)

tcp-keepalive 0   #tcp會話保持)

loglevel notice   #(生產環境至少是notice級別)

logfile ""   #(默認是stdout,也可指定具體文件)

databases 16   #set the number ofdatabasesthe default is DB0,使用select <dbid>可切庫,dbid is a number between 0 and databases-10-15))

save 900 1  #snapshot保存,會block客戶端請求,save ""表示不保存snapshot

save 300 10

save 60 10000

stop-writes-on-bgsave-error yes   #(在bgsave出錯時中止w

rdbcompression yes   #(壓縮DB

rdbchecksum yes

dbfilename dump.rdb

dir ./  #the working directory,指定dump.rdbappendonly.aof的存放位置,默認啓動進程時的當前目錄下)

slave-serve-stale-data yes

slave-read-only yes

repl-diskless-sync no

repl-diskless-sync-delay 5

repl-disable-tcp-nodelay no

slave-priority 100

appendonly no

appendfilename "appendonly.aof"   #(不用於master-slave,僅在redis重啓時將數據從disk讀入到內存)

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

aof-load-truncated yes

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

latency-monitor-threshold 0

notify-keyspace-events ""

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

hll-sparse-max-bytes 3000

activerehashing yes

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb60

client-output-buffer-limit pubsub 32mb 8mb60

hz 10

aof-rewrite-incremental-fsync yes

 

注:另redis.conf中註釋的命令:maxmemory <bytes>(當存的數據達到此處限定,會根據算法清以前的數據);maxmemory-policy noeviction(默認算法noeviction,算法有:volatile-lru-> remove the key with an expire set using an LRU algorithmallkeys-lru-> remove any key according to the LRU algorithmvolatile-random-> remove a random key with an expire setallkeys-random ->remove a random key, any keyvolatile-ttl -> remove the key with the nearest expire time(minor TTL)noeviction -> don't expire at all, just return an error on writeoperations

 

[root@server1 redis-3.0.7]# redis-server /etc/redis.conf &   #redis啓動)

……

8888:M 12 Sep 03:11:22.397# WARNING: The TCP backlog setting of 511 cannot be enforced because/proc/sys/net/core/somaxconn is set to the lower value of 128.

8888:M 12 Sep 03:11:22.397 # Serverstarted, Redis version 3.0.7

8888:M 12 Sep03:11:22.397 # WARNING overcommit_memory is set to 0! Background save may failunder low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to/etc/sysctl.conf and then reboot or run the command 'sysctlvm.overcommit_memory=1' for this to take effect.

8888:M 12 Sep 03:11:22.398 * The server isnow ready to accept connections on port 6379

 

[root@server1 redis-3.0.7]# netstat -tnulp | grep redis

tcp       0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      8888/redis-server *

tcp       0      0 :::6379                     :::*                        LISTEN      8888/redis-server *

 

[root@server1 redis-3.0.7]# redis-cli shutdown  #redis關閉)

8888:M 12 Sep 03:12:44.312 # User requestedshutdown...

8888:M 12 Sep 03:12:44.312 * Saving thefinal RDB snapshot before exiting.

8888:M 12 Sep 03:12:44.325 * DB saved ondisk

8888:M 12 Sep 03:12:44.325 # Redis is nowready to exit, bye bye...

[root@server1 redis-3.0.7]# netstat -tnulp|grep redis

 

[root@server1 redis-3.0.7]# vim /etc/sysctl.conf   #/proc/sys/net/core/somaxconn,監聽隊列的長度,對於一個TCP鏈接,ServerClient須要經過三次握手來創建網絡鏈接,當三次握手成功後,端口的狀態由LISTEN轉變爲ESTABLISHED,接着這條鏈路上就能夠開始傳送數據了,每個處於監聽Listen狀態的端口,都有本身的監聽隊列,對於一個常常處理新鏈接的高負載 web服務環境來講,默認的 128 過小了,大多數環境這個值建議增長到 1024 或者更多,服務進程(httpdsendmail)會本身限制偵聽隊列的大小(例如 sendmail(8),經常在它們的配置文件中有設置隊列大小的選項,大的偵聽隊列對防止拒絕服務DoS 攻擊也會有所幫助;/proc/sys/vm/overcommit_memory,默認0(啓發式過量,當userspace請求更多的內存時,內核嘗試估算出剩餘可用的內存),1(內核容許過量使用內存,直到用完爲止,主要用於科學計算),2(內核會用一個決不過量使用內存的算法設定,即系統整個內存地址空間不能超過swap+總內存的50%50/proc/sys/vm/overcommit_ratio的默認值,overcommit_memory2時要結合overcommit_ratio設定)

net.core.somaxconn = 1024

vm.overcommit_memory = 1

[root@server1 redis-3.0.7]# sysctl -p

……

[root@server1 redis-3.0.7]# cat /proc/sys/net/core/somaxconn

1024

[root@server1 redis-3.0.7]# cat /proc/sys/vm/overcommit_memory

1

 

[root@server1 redis-3.0.7]# redis-server /etc/redis.conf &

[1] 8985

[root@server1 redis-3.0.7]#                 _._                                                 

          _.-``__ ''-._                                            

     _.-``    `.  `_. ''-._           Redis 3.0.7(00000000/0) 64 bit

 .-`` .-```.  ```\/    _.,_ ''-._                                  

 (   '      ,       .-` | `,    )     Running in standalone mode

 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379

 |   `-._   `._    /    _.-'    |     PID: 8985

 `-._    `-._  `-./ _.-'    _.-'                                  

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |          http://redis.io       

 `-._    `-._`-.__.-'_.-'    _.-'                                  

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |                                 

 `-._    `-._`-.__.-'_.-'    _.-'                                  

     `-._    `-.__.-'    _.-'                                      

         `-._        _.-'                                          

              `-.__.-'                                               

 

8985:M 12 Sep 03:45:24.503 # Serverstarted, Redis version 3.0.7

8985:M 12 Sep 03:45:24.504 * DB loaded fromdisk: 0.000 seconds

8985:M 12 Sep 03:45:24.504 * The server isnow ready to accept connections on port 6379

[root@server1 redis-3.0.7]# ps aux | grepredis

root      8985  0.0  1.0 137448 2344 pts/0    Sl   03:45  0:00 redis-server *:6379        

root      8989  0.0  0.3 103252  824 pts/0    S+   03:45  0:00 grep redis

 

 

鏈接redis server的方式:

#redis-cli -h IP -p PORT cmd [arg [arg ...]]

#redis-cli -h IP -p PORT [-a PASSWORD]  (進入交互模式下操做)

#telnet IP PORT

#echo "cmd args" | nc IP PORT

 

[root@server1 ~]# redis-cli -h

Usage: redis-cli [OPTIONS] [cmd [arg [arg...]]]

  -h<hostname>      Server hostname(default: 127.0.0.1).

  -p<port>          Server port(default: 6379).

  -s<socket>        Server socket(overrides hostname and port).

  -a<password>      Password to usewhen connecting to the server.

 --stat             Print rollingstats about server: mem, clients, ...

 

[root@server1 ~]# redis-cli help

redis-cli 3.0.7

Type: "help @<group>" toget a list of commands in <group>

     "help <command>" for help on <command>

     "help <tab>" to get a list of possible help topics

     "quit" to exit

[root@server1 ~]# redis-cli help @generic   #(經常使用的命令:DEL key [key...]EXISTS key [key ...]KEYS patternEXPIRE key secondsEXPIREAT key timestampRENAME key newkeyTTL key

[root@server1 ~]# redis-cli help @string

[root@server1 ~]# redis-cli help @list

[root@server1 ~]# redis-cli help @set

[root@server1 ~]# redis-cli help @hash

[root@server1 ~]# redis-cli info   #(可查有關redis server的全部信息,有:serverclientsmemorypersistencestatsreplicationcpuclusterkeyspace

[root@server1 ~]# redis-cli info replication

 

[root@server1 ~]# redis-cli   #(可直接進入交互模式)

127.0.0.1:6379> help   #(或?,經常使用的命令setgetquitsavebgsavebgrewriteaofshutdwonshutdwonsavedelflushallinfoinfo cpukeys *dbsizeconfig get parameterconfig set parameter value在交互模式下改配置信息)

redis-cli 3.0.7

Type: "help @<group>" toget a list of commands in <group>

     "help <command>" for help on <command>

     "help <tab>" to get a list of possible help topics

     "quit" to exit

127.0.0.1:6379> set key1 value1

OK

127.0.0.1:6379> get key1

"value1"

127.0.0.1:6379> get key2   #(nil)爲空)

(nil)

127.0.0.1:6379> exists key1   #1True0False

(integer) 1

127.0.0.1:6379> keys *   #(取全部key

1) "key1"

127.0.0.1:6379> select 1   #(切庫,默認0-1516個庫,默認在第0庫)

OK

127.0.0.1:6379[1]> keys *

(empty list or set)

127.0.0.1:6379[1]> quit

 

[root@server1 ~]# redis-cli -h 10.96.20.113 -p 6379 set key2 value2   #(非交互模式下直接操做)

OK

[root@server1 ~]# redis-cli -h 10.96.20.113 -p 6379 get key2

"value2"

[root@server1 ~]# redis-cli -h 10.96.20.113 -p 6379 get key1

"value1"

 

[root@server1 ~]# telnet 10.96.20.113 6379   #(可在telnet下操做)

Trying 10.96.20.113...

Connected to 10.96.20.113.

Escape character is '^]'.

set key3 value3

+OK

get key3

$6

value3

^]

telnet> quit          

Connection closed.

 

[root@server1 ~]# echo "set key4 value4" | nc 10.96.20.113 6379   #(可經過nc操做)

+OK

[root@server1 ~]# echo "get key4"| nc 10.96.20.113 6379

$6

value4

 

 

[root@server1 ~]# vim /etc/redis.conf   #requirepass test,爲redis設置外部鏈接密碼,redis速度很快,在一臺性能很高的server上,一個外部的用戶可在1s內進行150K+次密碼嘗試,因此要指定很是強大的密碼防止暴力破解;rename-command set ""用於將認爲危險的命令屏蔽,rename-commandget gets用於將認爲危險的命令更名)

################################## SECURITY###################################

requirepass test

rename-command set ""

rename-command get gets

[root@server1 ~]# redis-cli shutdown

[root@server1 ~]# redis-server /etc/redis.conf &

……

[root@server1 ~]# redis-cli   #(或直接用#redis-cli -a test進入操做)

127.0.0.1:6379> keys *

(error) NOAUTH Authentication required.

127.0.0.1:6379>auth test

OK

127.0.0.1:6379> keys *

1) "key2"

2) "key3"

3) "key1"

127.0.0.1:6379> get key3

(error) ERR unknown command 'get'

127.0.0.1:6379> gets key3

"value3"

127.0.0.1:6379> set key4 value4

(error) ERR unknown command 'set'

127.0.0.1:6379> quit

[root@server1 ~]# vim /etc/redis.conf

#requirepass test

#rename-command set ""

#rename-command get gets

[root@server1 ~]# redis-cli shutdown

(error) NOAUTH Authentication required.

[root@server1 ~]# redis-cli -a test shutdown

13180:M 17 Sep 18:52:32.692 # Userrequested shutdown...

13180:M 17 Sep 18:52:32.692 * Saving thefinal RDB snapshot before exiting.

13180:M 17 Sep 18:52:32.695 * DB saved ondisk

13180:M 17 Sep 18:52:32.695 # Redis is nowready to exit, bye bye...

[1]+ Done                    redis-server/etc/redis.conf

[root@server1 ~]# redis-server /etc/redis.conf &

 

 

php安裝redis擴展(LNMP環境安裝見《理解LNMP》):

[root@server1 ~]# cd lnmp

[root@server1 lnmp]# tar xf phpredis-2.2.4.tar.gz   #(下載地址http://redis.googlecode.com/files/redis-2.4.2.tar.gz

[root@server1 lnmp]# cd phpredis-2.2.4

[root@server1 phpredis-2.2.4]# /usr/local/php/bin/phpize

Configuring for:

PHP Api Version:         20100412

Zend Module Api No:      20100525

Zend Extension Api No:   220100525

[root@server1 phpredis-2.2.4]# ./configure --with-php-config=/usr/local/php/bin/php-config

[root@server1 phpredis-2.2.4]# make && make install

……

Installing shared extensions:    /usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/

[root@server1 phpredis-2.2.4]# vim /etc/php.ini   #(在末尾添加以下一行,也可寫成兩行,extension= redis.soextension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/"

extension = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/redis.so"

[root@server1 phpredis-2.2.4]# service php-fpm restart

Gracefully shutting down php-fpm . done

Starting php-fpm  done

[root@server1 phpredis-2.2.4]# vim /usr/html/test.php

<?php

 $redis = new Redis();

 $redis ->connect("10.96.20.113",6379);

 /* $redis -> auth("test"); */

 $redis ->set("key8","value8");

 $var = $redis->get("key8");

 echo "$var\n";

?>

[root@server1 phpredis-2.2.4]# /usr/local/php/bin/php /usr/html/test.php   #(在命令行下操做腳本)

value8

wKioL1ffeaHxWnNbAABeH5sJgTY626.jpg

wKiom1ffea6RKbcRAAA-ayChIoE774.jpg

 

 

python操做redis

[root@server1 ~]# wget --no-check-certificate  https://pypi.python.org/packages/source/r/redis/redis-2.10.1.tar.gz

[root@server1 ~]# tar xf redis-2.10.1.tar.gz

[root@server1 ~]# cd redis-2.10.1

[root@server1 redis-2.10.1]# python setup.py install

[root@server1 redis-2.10.1]# python -V

Python 2.6.6

[root@server1 redis-2.10.1]# vim /usr/html/python_redis.py

#!/usr/bin/python

#

import redis

r = redis.Redis(host='10.96.20.113',port=6379,db=0)

r.set('key9','value9')

print r.get('key9')

[root@server1 redis-2.10.1]# python /usr/html/python_redis.py

value9

 

 

redis數據類型(stringlistsetzsethash):

string

字符串類型是redis最簡單的數據類型,若只使用stringredis就是一個持久化的memcached server,實際redisstring功能要比memcached多;

1)常規的stringvalue能夠是任何類型的string,包括binary,可保存jpg圖片,value的長度不能超過1G#redis-cliset mykey "mybinary safe value"#redis-cli get mykey);

2string其它功能,對valuenumerical可進行加減操做:

[root@server1 ~]# redis-cli

127.0.0.1:6379> help @string

……

127.0.0.1:6379> help incr

 INCR key

 summary: Increment the integer value of a key by one

 since: 1.0.0

 group: string

127.0.0.1:6379> help incrby

 INCRBY key increment

 summary: Increment the integer value of a key by the given amount

 since: 1.0.0

 group: string

127.0.0.1:6379> set counter 21

OK

127.0.0.1:6379>incr counter

(integer) 22

127.0.0.1:6379> incr counter

(integer) 23

127.0.0.1:6379> incrby counter 2

(integer) 25

127.0.0.1:6379> decr counter

(integer) 24

127.0.0.1:6379> decrby counter 2

(integer) 22

127.0.0.1:6379> get counter

"22"

3)爲key設置新值並返回原值(打印出的是原值,但原值已被覆蓋爲新設置的值):

127.0.0.1:6379> help getset

 GETSET key value

 summary: Set the string value of a key and return its old value

 since: 1.0.0

 group: string

127.0.0.1:6379> getset key2 value2.2

"value2"

127.0.0.1:6379> get key2

"value2.2"

4)支持批量rw操做:

127.0.0.1:6379> help mset

 MSET key value [key value ...]

 summary: Set multiple keys to multiple values

 since: 1.0.1

 group: string

127.0.0.1:6379> help mget

 MGET key [key ...]

 summary: Get the values of all the given keys

 since: 1.0.0

 group: string

127.0.0.1:6379> mset key4 value4 key5 value5 key6 value6

OK

127.0.0.1:6379> mget key4 key5 key6

1) "value4"

2) "value5"

3) "value6"

5)支持部分修改操做:

127.0.0.1:6379> help append

 APPEND key value

 summary: Append a value to a key

 since: 2.0.0

 group: string

127.0.0.1:6379> append key6 6

(integer) 7

127.0.0.1:6379> get key6

"value66"

6)查看value的長度:

127.0.0.1:6379> help strlen

 STRLEN key

 summary: Get the length of the value stored in a key

 since: 2.2.0

 group: string

127.0.0.1:6379> strlen key6

(integer) 7

127.0.0.1:6379> strlen key5

(integer) 6

 

listredis lists are implemented with linked lists because for a database system it is crucial to be able to add elements to a very logn list in a very fast way,another strong advantage is,as you'll see in a moment,that redis lists can be taken atconstant length in constant time.):

redis listslinked lists實現的緣由:能快速的在很大的列表上添加元素,這是DB系統的重要特性,redis list能在常數時間取得常數長度;

redis list可用於程序中的聊天功能;

127.0.0.1:6379> help @list

……

127.0.0.1:6379> flushall

OK

127.0.0.1:6379> keys *

(empty list or set)

127.0.0.1:6379> lpush k1234 v1 v2 v3

(integer) 3

127.0.0.1:6379> lpush k1234 v4

(integer) 4

127.0.0.1:6379> llen k1234

(integer) 4

127.0.0.1:6379> lrange k1234 0 3

1) "v4"

2) "v3"

3) "v2"

4) "v1"

127.0.0.1:6379> lrem k1234 1 v4

(integer) 1

127.0.0.1:6379> lrange k1234 0 3

1) "v3"

2) "v2"

3) "v1"

127.0.0.1:6379> lrem k1234 1 v2

(integer) 1

127.0.0.1:6379> lrange k1234 0 1

1) "v3"

2) "v1"

127.0.0.1:6379> lpop k1234   #(刪除並彈出列表的第一個element

"v3"

127.0.0.1:6379> linsert k1234 before v1v4

(integer) 2

127.0.0.1:6379> lrange k1234 0 8

1) "v4"

2) "v1"

 

setset是未排序的集合,元素是二進制安全的string,操做有:saddsmemberssismembersremsdiff差集、sinter交集、sunion並集等,set可實現標籤功能,開發可用於保存關係;sorted_set中的數據有score屬性,並在寫入時會按score進行排序,操做有:zaddzrangezcorezrangebyscorezcount等):

127.0.0.1:6379> help @set

……

127.0.0.1:6379> help @sorted_set

……

127.0.0.1:6379> flushall

OK

127.0.0.1:6379> sadd k1234 v1 v2 v3 v4   #(向set中添加多個新元素)

(integer) 4

127.0.0.1:6379> smembers k1234

1) "v3"

2) "v4"

3) "v2"

4) "v1"

127.0.0.1:6379> sismember k1234 v3   #(判斷set中的某個element是否存在,1True0False

(integer) 1

127.0.0.1:6379> srem k1234 v4 v3

(integer) 2

127.0.0.1:6379> smembers k1234

1) "v2"

2) "v1"

127.0.0.1:6379> flushall

OK

127.0.0.1:6379> zadd week 1 mon 2 tue

(integer) 2

127.0.0.1:6379> zadd week 4 thu 6 sat

(integer) 2

127.0.0.1:6379> zadd week 3 wed 5 fri 7sun

(integer) 3

127.0.0.1:6379> zrange week 0 6

1) "mon"

2) "tue"

3) "wed"

4) "thu"

5) "fri"

6) "sat"

7) "sun"

127.0.0.1:6379> zscore week sat   #(查看value在集合中的index位置)

"6"

127.0.0.1:6379> zrangebyscore week 2 5

1) "tue"

2) "wed"

3) "thu"

4) "fri"

127.0.0.1:6379> zadd hacker 1940 'alankay' 1953 'richard stallman' 1965 'yukihiro matsumto' 1969 'linus torvalds'1912 'alan turing'

(integer) 5

127.0.0.1:6379> zrange hacker 0 4

1) "alan turing"

2) "alan kay"

3) "richard stallman"

4) "yukihiro matsumto"

5) "linus torvalds"

127.0.0.1:6379> zrevrange hacker 0 4

1) "linus torvalds"

2) "yukihiro matsumto"

3) "richard stallman"

4) "alan kay"

5) "alan turing"

127.0.0.1:6379> zremrangebyscore hacker-inf 1950   #(刪除key1950年以前的記錄)

(integer) 2

127.0.0.1:6379> zrange hacker 0 4

1) "richard stallman"

2) "yukihiro matsumto"

3) "linus torvalds"

 

hash(存儲key對多個屬性的數據):

127.0.0.1:6379> help @hash

……

127.0.0.1:6379> flushall

OK

127.0.0.1:6379> help hset

 HSET key field value

 summary: Set the string value of a hash field

 since: 2.0.0

 group: hash

127.0.0.1:6379> hset test name jowin

(integer) 1

127.0.0.1:6379> hset test age 18

(integer) 1

127.0.0.1:6379> hset test sex male

(integer) 1

127.0.0.1:6379> hvals test

1) "jowin"

2) "18"

3) "male"

127.0.0.1:6379> hgetall test

1) "name"

2) "jowin"

3) "age"

4) "18"

5) "sex"

6) "male"

127.0.0.1:6379> hdel test sex

(integer) 1

127.0.0.1:6379> hvals test

1) "jowin"

2) "18"

127.0.0.1:6379> hmget test name age

1) "jowin"

2) "18"

127.0.0.1:6379> quit

[root@server1 ~]# redis-cli shutdown

 

pub/sub,發佈/訂閱是一種消息通訊模式,主要目的解耦消息發佈者和消息訂閱者之間的耦合,也解決二者在物理部署上的耦合,與設計模式中的觀察者模式相似;

redis做爲一個pub/subserver,在訂閱者和發佈者之間起到了消息路由的功能,訂閱者可經過publishsubscribe命令向redis server訂閱本身感興趣的消息類型,redis將消息類型稱爲channel,當發佈者經過publish命令向redis server發送特定類型的消息時,訂閱該消息的全部client都會收到此消息,消息的傳遞是多對多的,一個client可訂閱多個channel,也可向多個channel發送消息;

redis可將數據推到某個信息管道中,其它人可經過訂閱這些管道來獲取推送過來的消息;

127.0.0.1:6379> subscribe channelone  

Reading messages... (press Ctrl-C to quit)

1) "subscribe"

2) "channelone"

3) (integer) 1

1) "message"

2) "channelone"

3) "hello"

1) "message"

2) "channelone"

3) "world"

127.0.0.1:6379> publish channelone hello   #(在另外一終端執行)

(integer) 1

127.0.0.1:6379> publish channelone world

(integer) 1

127.0.0.1:6379> psubscribe channel*   #psubscribe監聽多個信道)

Reading messages... (press Ctrl-C to quit)

1) "psubscribe"

2) "channel*"

3) (integer) 1

1) "pmessage"

2) "channel*"

3) "channelone"

4) "hello world"

1) "pmessage"

2) "channel*"

3) "channeltwo"

4) "welcome"

127.0.0.1:6379> publish channelone "hello world"   #(在另外一終端執行)

(integer) 1

127.0.0.1:6379> publish channeltwo "welcome"

(integer) 1

 

過時機制:

redis對過時key採用了lazy expiration,兩種方式:passive way(在訪問key時斷定key是否過時,若是過時則進行過時處理);active way(每秒對volatile keys進行抽樣測試,若是有過時key,將對全部過時key進行處理);

127.0.0.1:6379> flushall

6144:M 18 Sep 03:20:04.618 * DB saved ondisk

OK

127.0.0.1:6379> keys *

(empty list or set)

127.0.0.1:6379> set key1 value1

OK

127.0.0.1:6379> exists key1

(integer) 1

127.0.0.1:6379> ttl key1   #-1爲永不過時,-2爲過時)

(integer) -1

127.0.0.1:6379> help expire

 EXPIRE key seconds

 summary: Set a key's time to live in seconds

 since: 1.0.0

 group: generic

127.0.0.1:6379> help expireat

 EXPIREAT key timestamp

 summary: Set the expiration for a key as a UNIX timestamp

 since: 1.2.0

 group: generic

127.0.0.1:6379> expire key1 5

(integer) 1

127.0.0.1:6379> ttl key1

(integer) 2

127.0.0.1:6379> ttl key1

(integer) -2

127.0.0.1:6379> get key1

(nil)

 

transaction

redis支持簡單的組合型的命令,例如以nx結尾的命令用於判斷key所對應的value沒有時也進行某個命令;

127.0.0.1:6379> help @transactions

……

127.0.0.1:6379> keys *

(empty list or set)

127.0.0.1:6379> setnx key1 value1

(integer) 1

127.0.0.1:6379> get key1

"value1"

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set key1 value2

QUEUED

127.0.0.1:6379> set key1 value3

QUEUED

127.0.0.1:6379> set key1 value4   #(當事務中有錯誤時將都不執行)

QUEUED

127.0.0.1:6379> exec   #(執行以上事務,discard爲取消事務)

1) OK

2) OK

3) OK

127.0.0.1:6379> get key1

"value4"

 

 

redis多實例:

MySQL的多實例,兩種方式(不一樣的配置文件,不一樣的程序目錄,不一樣的數據目錄;同一個配置文件,不一樣的程序目錄,不一樣的數據目錄);

redis的多實例(不一樣的配置文件,同一個程序目錄,不一樣的數據目錄);

[root@server1 ~]# mkdir -pv /var/lib/redis/{6379,6380}

mkdir: created directory `/var/lib/redis'

mkdir: created directory`/var/lib/redis/6379'

mkdir: created directory`/var/lib/redis/6380'

[root@server1 ~]# mv /etc/redis.conf/etc/redis_6379.conf

[root@server1 ~]# cp /etc/redis_6379.conf/etc/redis_6380.conf

[root@server1 ~]# vim /etc/redis_6379.conf

pidfile /var/run/redis_6379.pid

port 6379

dir /var/lib/redis/6379/

[root@server1 ~]# vim /etc/redis_6380.conf

pidfile /var/run/redis_6380.pid

port 6380

dir /var/lib/redis/6380/

[root@server1 ~]# redis-server /etc/redis_6379.conf &

[1] 5998

[root@server1 ~]#                 _._                                                 

          _.-``__ ''-._                                            

     _.-``    `.  `_. ''-._           Redis 3.0.7(00000000/0) 64 bit

 .-`` .-```.  ```\/    _.,_ ''-._                                  

 (   '      ,       .-` | `,    )     Running in standalone mode

 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379

 |    `-._  `._    /     _.-'   |     PID: 5998

 `-._    `-._  `-./ _.-'    _.-'                                  

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |          http://redis.io       

 `-._    `-._`-.__.-'_.-'    _.-'                                  

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |                                 

 `-._    `-._`-.__.-'_.-'    _.-'                                  

     `-._    `-.__.-'    _.-'                                      

         `-._        _.-'                                          

              `-.__.-'                                               

 

5998:M 18 Sep 01:06:36.665 # Serverstarted, Redis version 3.0.7

5998:M 18 Sep 01:06:36.665 * The server isnow ready to accept connections on port 6379

[root@server1 ~]# redis-server /etc/redis_6380.conf &

[2] 6001

[root@server1 ~]#                 _._                                                 

          _.-``__ ''-._                                            

     _.-``    `.  `_. ''-._           Redis 3.0.7(00000000/0) 64 bit

 .-`` .-```.  ```\/    _.,_ ''-._                                   

 (   '      ,       .-` | `,    )     Running in standalone mode

 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6380

 |   `-._   `._    /    _.-'    |     PID: 6001

 `-._    `-._  `-./ _.-'    _.-'                                   

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |          http://redis.io       

 `-._    `-._`-.__.-'_.-'    _.-'                                  

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |                                 

 `-._    `-._`-.__.-'_.-'    _.-'                                  

     `-._    `-.__.-'    _.-'                                      

         `-._        _.-'                                          

              `-.__.-'                                              

 

6001:M 18 Sep 01:07:03.936 # Serverstarted, Redis version 3.0.7

6001:M 18 Sep 01:07:03.936 * The server isnow ready to accept connections on port 6380

[root@server1 ~]# netstat -tnlp | grep redis

tcp       0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      5998/redis-server *

tcp       0      0 0.0.0.0:6380                0.0.0.0:*                   LISTEN      6001/redis-server *

tcp       0      0 :::6379                     :::*                        LISTEN      5998/redis-server *

tcp       0      0 :::6380                     :::*                        LISTEN      6001/redis-server *

 

[root@server1 ~]# redis-cli -p 6379

127.0.0.1:6379> keys *

(empty list or set)

127.0.0.1:6379> set k1 v1

OK

127.0.0.1:6379> get k1

"v1"

127.0.0.1:6379> quit

[root@server1 ~]# redis-cli -p 6380

127.0.0.1:6380> keys *

(empty list or set)

127.0.0.1:6380> set k1 v1

OK

127.0.0.1:6380> get k1

"v1"

127.0.0.1:6380> quit

 

 

redis主從同步(http://www.redis.io/topics/replication):

wKioL1ffer-SiujnAAAeykOYouw962.jpg

Redis replication is a very simple to useand configure master-slave replication that allows slave Redis servers to beexact copies of master servers. The following are some very important factsabout Redis replication:

1Redis uses asynchronous replication. Starting with Redis 2.8,however, slaves periodically acknowledge the amount of data processed from thereplication stream.

2A master can have multiple slaves.

3Slaves are able to accept connections from other slaves. Aside fromconnecting a number of slaves to the same master, slaves can also be connectedto other slaves in a cascading-like structure.

4Redis replication is non-blocking on the master side. This meansthat the master will continue to handle queries when one or more slaves performthe initial synchronization.

5Replication is also non-blocking on the slave side. While the slaveis performing the initial synchronization, it can handle queries using the oldversion of the dataset, assuming you configured Redis to do so in redis.conf.Otherwise, you can configure Redis slaves to return an error to clients if thereplication stream is down. However, after the initial sync, the old datasetmust be deleted and the new one must be loaded. The slave will block incomingconnections during this brief window (that can be as long as many seconds forvery large datasets).

6Replication can be used both for scalability, in order to havemultiple slaves for read-only queries (for example, slow O(N) operations can beoffloaded to slaves), or simply for data redundancy.

7It is possible to use replication to avoid the cost of having themaster write the full dataset to disk: a typical technique involves configuringyour master redis.conf to avoid persisting to disk at all, then connect a slaveconfigured to save from time to time, or with AOF enabled. However this setupmust be handled with care, since a restarting master will start with an emptydataset: if the slave tries to synchronized with it, the slave will be emptiedas well.

 

In setups where Redis replication is used,it is strongly advised to have persistence turned on inthe masterEvery time data safety is important, andreplication is used with master configured without persistence, auto restart of instances should be disabled.

 

How Redis replication works

1If you set up a slave, upon connection it sends a PSYNC command.

2If this is a reconnection and the master has enough backlog, onlythe difference (what the slave missed) is sent. Otherwise what is called a fullresynchronization is triggered.

3When a full resynchronization is triggered, the master starts abackground saving process in order to produce an RDB file. At the same time itstarts to buffer all new write commands received from the clients. When thebackground saving is complete, the master transfers the database file to theslave, which saves it on disk, and then loads it into memory. The master willthen send all buffered commands to the slave. This is done as a stream ofcommands and is in the same format of the Redis protocol itself.

You can try it yourself via telnet. Connectto the Redis port while the server is doing some work and issue the SYNCcommand. You'll see a bulk transfer and then every command received by themaster will be re-issued in the telnet session.

Slaves are able to automatically reconnectwhen the master-slave link goes down for some reason. If the master receivesmultiple concurrent slave synchronization requests, it performs a singlebackground save in order to serve all of them.

 

Partial resynchronization

1Starting with Redis 2.8, master and slave are usually able tocontinue the replication process without requiring a full resynchronizationafter the replication link went down.

2This works by creating an in-memory backlog of the replicationstream on the master side. The master and all the slaves agree on a replicationoffset and a master run ID, so when the link goes down, the slave willreconnect and ask the master to continue the replication. Assuming the masterrun ID is still the same, and that the offset specified is available in thereplication backlog, replication will resume from the point where it left off.If either of these conditions are unmet, a full resynchronization is performed(which is the normal pre-2.8 behavior). As the run ID of the connected masteris not persisted to disk, a full resynchronization is needed when the slaverestarts.

3The new partial resynchronization feature uses the PSYNC commandinternally, while the old implementation uses the SYNC command. Note that aRedis slave is able to detect if the server it is talking with does not supportPSYNC, and will use SYNC instead.

 

slave-side

[root@server2 ~]# vim /etc/redis.conf   #salveof指定masterIPPORT;若在master上開啓了requirepass選項,要在slave上開啓masterauth,後跟master上設置的密碼;slave-server-stale-datawhen a salveloses its connection with the master,or when the replication is still inprogress,the slave can act in two different ways:(1)default yes,the slave willstill reply to client requests,possibly with out of date data,or the data setmay just be empty if this is the first synchronization.(2)no,the slave will replywith an error "sync with master in progress" to all the kind ofcommands but to INFO and SLAVEOF

#################################REPLICATION #################################

salveof 10.96.20.113 6379

# masterauth <master-password>

slave-serve-stale-data yes

slave-read-only yes

#-------------------------------------------------------

# WARNING: DISKLESS REPLICATION ISEXPERIMENTAL CURRENTLY

#-------------------------------------------------------

repl-diskless-sync no

repl-diskless-sync-delay 5

# repl-ping-slave-period 10

# repl-timeout 60

repl-disable-tcp-nodelay no

# repl-backlog-size 1mb

# repl-backlog-ttl 3600

slave-priority 100

# min-slaves-to-write 3

# min-slaves-max-lag 10

 

master-side

[root@server1 ~]# redis-server /etc/redis.conf &

 

slave-side

[root@server2 ~]# redis-server /etc/redis.conf &

[1] 11669

[root@server2 ~]#                 _._                                                 

          _.-``__ ''-._                                            

     _.-``    `.  `_. ''-._           Redis 3.0.7(00000000/0) 64 bit

 .-`` .-```.  ```\/    _.,_ ''-._                                  

 (   '      ,       .-` | `,    )     Running in standalone mode

 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379

 |   `-._   `._    /     _.-'   |     PID: 11669

 `-._    `-._  `-./ _.-'    _.-'                                  

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |          http://redis.io       

 `-._    `-._`-.__.-'_.-'    _.-'                                  

 |`-._`-._   `-.__.-'    _.-'_.-'|                                 

 |   `-._`-._        _.-'_.-'    |                                 

 `-._    `-._`-.__.-'_.-'    _.-'                                   

     `-._    `-.__.-'    _.-'                                      

         `-._        _.-'                                          

              `-.__.-'                                              

 

11669:S 18 Sep 02:34:33.529 # Serverstarted, Redis version 3.0.7

11669:S 18 Sep 02:34:33.530 * The server isnow ready to accept connections on port 6379

11669:S 18 Sep 02:34:34.522 * Connecting toMASTER 10.96.20.113:6379

11669:S 18 Sep 02:34:34.522 * MASTER<-> SLAVE sync started

11669:S 18 Sep 02:34:34.523 * Non blockingconnect for SYNC fired the event.

11669:S 18 Sep 02:34:34.523 * Masterreplied to PING, replication can continue...

11669:S 18 Sep 02:34:34.523 * Partialresynchronization not possible (no cached master)

11669:S 18 Sep 02:34:34.524 * Full resyncfrom master: 545af66a04371d0fee71b683b2ad358adfd0d6a8:1

11669:S 18 Sep 02:34:34.629 * MASTER<-> SLAVE sync: receiving 18 bytes from master

11669:S 18 Sep 02:34:34.629 * MASTER<-> SLAVE sync: Flushing old data

11669:S 18 Sep 02:34:34.629 * MASTER<-> SLAVE sync: Loading DB in memory

11669:S 18 Sep 02:34:34.629 * MASTER<-> SLAVE sync: Finished with success

 

測試:

[root@server1 ~]# redis-cli   #(在masterw數據,到slave上查看)

127.0.0.1:6379> keys *

(empty list or set)

127.0.0.1:6379> set key1 value1

OK

127.0.0.1:6379> get key1

"value1"

 

[root@server2 ~]# redis-cli

127.0.0.1:6379> keys *

1) "key1"

127.0.0.1:6379> get key1

"value1"

127.0.0.1:6379> set key2 value2   #slaver不能w

(error) READONLY You can't write against a readonly slave.

127.0.0.1:6379>monitor   #(交互模式下在slave上開啓監控,再在masterw數據,將會實時顯示)

OK

1474191743.144953 [0 10.96.20.113:6379]"PING"

1474191753.242462 [0 10.96.20.113:6379]"PING"

1474191756.972746 [0 10.96.20.113:6379]"set" "key2" "value2"

1474191763.340888 [0 10.96.20.113:6379]"PING"

相關文章
相關標籤/搜索