0. NoSQL 產(chǎn)品(key-value)
RDBMS :MySQL,Oracle ,MSSQL,PGNoSQL:Redis,MongoDB,列存儲(chǔ)存儲(chǔ)相關(guān)NewSQL----->分布式數(shù)據(jù)庫(kù)架構(gòu)(學(xué)習(xí)了MongoDB)緩存產(chǎn)品介紹:memcached (大公司會(huì)做二次開(kāi)發(fā))redisTair
1. Redis功能介紹
數(shù)據(jù)類型豐富? ? (筆試、面試)*****支持持久化? ? ? (筆試、面試) *****多種內(nèi)存分配及回收策略支持事務(wù)? ? ? ? ? ? (面試)? ? ****消息隊(duì)列、消息訂閱 支持高可用? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ****支持分布式分片集群 (面試)? *****緩存穿透\雪崩(筆試、面試)? *****Redis API? ? ? ? ? ? ? ? ? **
2、企業(yè)緩存產(chǎn)品介紹
Memcached:優(yōu)點(diǎn):高性能讀寫(xiě)、單一數(shù)據(jù)類型、支持客戶端式分布式集群、一致性hash多核結(jié)構(gòu)、多線程讀寫(xiě)性能高。缺點(diǎn):無(wú)持久化、節(jié)點(diǎn)故障可能出現(xiàn)緩存穿透、分布式需要客戶端實(shí)現(xiàn)、跨機(jī)房數(shù)據(jù)同步困難、架構(gòu)擴(kuò)容復(fù)雜度高Redis:? 優(yōu)點(diǎn):高性能讀寫(xiě)、多數(shù)據(jù)類型支持、數(shù)據(jù)持久化、高可用架構(gòu)、支持自定義虛擬內(nèi)存、支持分布式分片集群、單線程讀寫(xiě)性能極高缺點(diǎn):多線程讀寫(xiě)較Memcached慢新浪、京東、直播類平臺(tái)、網(wǎng)頁(yè)游戲? ? memcache與redis在讀寫(xiě)性能的對(duì)比memcached 適合,多用戶訪問(wèn),每個(gè)用戶少量的rwredis? ? 適合,少用戶訪問(wèn),每個(gè)用戶大量rw? ? ? ? ? ? Tair:優(yōu)點(diǎn):高性能讀寫(xiě)、支持三種存儲(chǔ)引擎(ddb、rdb、ldb)、支持高可用、支持分布式分片集群、支撐了幾乎所有淘寶業(yè)務(wù)的緩存。? ? 缺點(diǎn):?jiǎn)螜C(jī)情況下,讀寫(xiě)性能較其他兩種產(chǎn)品較慢
3、Redis使用場(chǎng)景介紹
Memcached:多核的緩存服務(wù),更加適合于多用戶并發(fā)訪問(wèn)次數(shù)較少的應(yīng)用場(chǎng)景Redis:?jiǎn)魏说木彺娣?wù),單節(jié)點(diǎn)情況下,更加適合于少量用戶,多次訪問(wèn)的應(yīng)用場(chǎng)景。Redis一般是單機(jī)多實(shí)例架構(gòu),配合redis集群出現(xiàn)。
4、Redis安裝部署:
下載:wget http://download.redis.io/releases/redis-3.2.12.tar.gz解壓:上傳至/datatar xzf redis-3.2.12.tar.gzmv redis-3.2.12redis安裝:yum-y install gcc automake autoconf libtool makecd redismake環(huán)境變量:vim/etc/profileexportPATH=/data/redis/src:$PATHsource/etc/profile 啟動(dòng):redis-server&連接測(cè)試:redis-cli127.0.0.1:6379>setnum10OK127.0.0.1:6379>getnum10
5、Redis基本管理操作
5.1基礎(chǔ)配置文件介紹
mkdir/data/6379cat>/data/6379/redis.conf<<EOFdaemonize yesport6379logfile/data/6379/redis.logdir/data/6379dbfilename dump.rdbEOFredis-cli shutdown redis-server/data/6379/redis.conf netstat-lnp|grep63+++++++++++配置文件說(shuō)明++++++++++++++redis.conf是否后臺(tái)運(yùn)行:daemonize yes默認(rèn)端口:port6379日志文件位置logfile/var/log/redis.log持久化文件存儲(chǔ)位置dir/data/6379RDB持久化數(shù)據(jù)文件:dbfilename dump.rdb++++++++++++++++++++++++++++++++++++++redis-cli127.0.0.1:6379>setname zhangsan OK127.0.0.1:6379>getname"zhangsan"
5.2 redis安全配置
redis默認(rèn)開(kāi)啟了保護(hù)模式,只允許本地回環(huán)地址登錄并訪問(wèn)數(shù)據(jù)庫(kù)。禁止protected-modeprotected-mode yes/no (保護(hù)模式,是否只允許本地訪問(wèn))(1)Bind:指定IP進(jìn)行監(jiān)聽(tīng)vim/data/6379/redis.confbind10.0.0.51127.0.0.1(2)增加requirepass{password}vim/data/6379/redis.confrequirepass123456----------驗(yàn)證-----方法一:[root@db03~]# redis-cli -a 123456127.0.0.1:6379>set name zhangsanOK127.0.0.1:6379>exit方法二:[root@db03~]# redis-cli127.0.0.1:6379>auth123456OK127.0.0.1:6379>set a b[root@db01src]# redis-cli -a 123 -h 10.0.0.51 -p 637910.0.0.51:6379>set b2OK
5.3 在線查看和修改配置
CONFIG GET *CONFIG GET requirepassCONFIG GET r*CONFIG SET requirepass 123
5.4 redis持久化(內(nèi)存數(shù)據(jù)保存到磁盤(pán))
RDB、AOFRDB 持久化? ? 可以在指定的時(shí)間間隔內(nèi)生成數(shù)據(jù)集的 時(shí)間點(diǎn)快照(point-in-time snapshot)。? ? 優(yōu)點(diǎn):速度快,適合于用做備份,主從復(fù)制也是基于RDB持久化功能實(shí)現(xiàn)的。? ? 缺點(diǎn):會(huì)有數(shù)據(jù)丟失rdb持久化核心配置參數(shù):vim/data/6379/redis.confdir/data/6379dbfilename dump.rdbsave9001save30010save6010000配置分別表示:900秒(15分鐘)內(nèi)有1個(gè)更改300秒(5分鐘)內(nèi)有10個(gè)更改60秒內(nèi)有10000個(gè)更改? AOF 持久化(append-only log file)記錄服務(wù)器執(zhí)行的所有寫(xiě)操作命令,并在服務(wù)器啟動(dòng)時(shí),通過(guò)重新執(zhí)行這些命令來(lái)還原數(shù)據(jù)集。? ? AOF 文件中的命令全部以 Redis 協(xié)議的格式來(lái)保存,新命令會(huì)被追加到文件的末尾。? ? 優(yōu)點(diǎn):可以最大程度保證數(shù)據(jù)不丟? ? 缺點(diǎn):日志記錄量級(jí)比較大AOF持久化配置appendonly yesappendfsync alwaysappendfsync everysecappendfsync no是否打開(kāi)aof日志功能每1個(gè)命令,都立即同步到aof 每秒寫(xiě)1次寫(xiě)入工作交給操作系統(tǒng),由操作系統(tǒng)判斷緩沖區(qū)大小,統(tǒng)一寫(xiě)入到aof.vim/data/6379/redis.confappendonly yesappendfsync everysec 面試: redis 持久化方式有哪些?有什么區(qū)別?rdb:基于快照的持久化,速度更快,一般用作備份,主從復(fù)制也是依賴于rdb持久化功能aof:以追加的方式記錄redis操作日志的文件??梢宰畲蟪潭鹊谋WCredis數(shù)據(jù)安全,類似于mysql的binlog
6、Redis數(shù)據(jù)類型(筆試):
##6.1介紹String :? ? ? 字符類型Hash:? ? ? ? 字典類型List:? ? ? ? 列表? ? Set:? ? ? ? ? 集合 Sortedset:? 有序集合
need-to-insert-img
image.png
6.2 KEY的通用操作
KEYS *? keys a? keys a*? ? 查看已存在所有鍵的名字? ****TYPE? ? ? ? ? ? ? ? ? ? ? ? 返回鍵所存儲(chǔ)值的類型? ? ****EXPIRE\ PEXPIRE? ? ? ? ? ? 以秒\毫秒設(shè)定生存時(shí)間? ? ? ***TTL\ PTTL? ? ? ? ? ? ? ? ? 以秒\毫秒為單位返回生存時(shí)間 ***PERSIST? ? ? ? ? ? ? ? ? ? 取消生存時(shí)間設(shè)置? ? ? ? ? ? ***DEL? ? ? ? ? ? ? ? ? ? ? ? 刪除一個(gè)keyEXISTS? ? ? ? ? ? ? ? ? ? ? 檢查是否存在RENAME? ? ? ? ? ? ? ? ? ? ? 變更KEY名---例子:127.0.0.1:6379> set name zhangsan 127.0.0.1:6379> EXPIRE name 60(integer)1127.0.0.1:6379> ttl name(integer)57127.0.0.1:6379> set a b ex 60OK127.0.0.1:6379> ttl a127.0.0.1:6379> PERSIST a(integer)1127.0.0.1:6379> ttl a(integer)-1
6.3 Strings
應(yīng)用場(chǎng)景session 共享常規(guī)計(jì)數(shù):微博數(shù),粉絲數(shù),訂閱、禮物key:value----------(1) set name zhangsan? (2) MSET id 101 name zhangsan age 20 gender m 等價(jià)于以下操作: SET id 101? set name zhangsan? set age 20? set gender m(3)計(jì)數(shù)器每點(diǎn)一次關(guān)注,都執(zhí)行以下命令一次127.0.0.1:6379> incr num顯示粉絲數(shù)量:127.0.0.1:6379> get num暗箱操作:127.0.0.1:6379> INCRBY num 10000(integer)10006127.0.0.1:6379> get num"10006"127.0.0.1:6379> DECRBY num 10000(integer)6127.0.0.1:6379> get num"6"詳細(xì)的例子:------------------------------------增set mykey"test"為鍵設(shè)置新值,并覆蓋原有值getset mycounter 0? ? ? ? ? ? ? 設(shè)置值,取值同時(shí)進(jìn)行setex mykey 10"hello"設(shè)置指定 Key 的過(guò)期時(shí)間為10秒,在存活時(shí)間可以獲取valuesetnx mykey"hello"若該鍵不存在,則為鍵設(shè)置新值mset key3"zyx"key4"xyz"批量設(shè)置鍵刪del mykey? ? ? ? ? ? ? ? ? ? ? ? 刪除已有鍵改append mykey"hello"若該鍵并不存在,返回當(dāng)前 Value 的長(zhǎng)度? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 該鍵已經(jīng)存在,返回追加后 Value的長(zhǎng)度incr mykey? ? ? ? ? ? ? ? ? ? ? 值增加1,若該key不存在,創(chuàng)建key,初始值設(shè)為0,增加后結(jié)果為1decrby? mykey? 5? ? ? ? ? ? ? ? 值減少5setrange mykey 20 dd? ? ? ? ? ? 把第21和22個(gè)字節(jié),替換為dd,超過(guò)value長(zhǎng)度,自動(dòng)補(bǔ)0查? exists mykey? ? ? ? ? ? ? ? ? ? 判斷該鍵是否存在,存在返回 1,否則返回0get mykey? ? ? ? ? ? ? ? ? ? ? 獲取Key對(duì)應(yīng)的valuestrlen mykey? ? ? ? ? ? ? ? ? ? 獲取指定 Key 的字符長(zhǎng)度ttl mykey? ? ? ? ? ? ? ? ? ? ? 查看一下指定 Key 的剩余存活時(shí)間(秒數(shù))getrange mykey 1 20? ? ? ? ? ? 獲取第2到第20個(gè)字節(jié),若20超過(guò)value長(zhǎng)度,則截取第2個(gè)和后面所有的mget key3 key4? ? ? ? ? ? ? ? ? 批量獲取鍵
6.4 hash類型(字典類型)
應(yīng)用場(chǎng)景:存儲(chǔ)部分變更的數(shù)據(jù),如用戶信息等。最接近mysql表結(jié)構(gòu)的一種類型主要是可以做數(shù)據(jù)庫(kù)緩存。存數(shù)據(jù):hmset stu? id101name zhangsan age20gender mhmset stu1 id102name zhangsan1 age21gender f取數(shù)據(jù):HMGETstu id name age genderHMGETstu1 id name age genderselectconcat("hmset city_",id," id ",id," name ",name," countrycode ",countrycode," district ",district," population ",population)fromcity limit10intooutfile'/tmp/hmset.txt'---------------------更多的例子增hset myhash field1"s"若字段field1不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的Hashes,Hashes中,key為field1,并設(shè)value為s ,若存在會(huì)覆蓋原valuehsetnx myhash field1 s? ? 若字段field1不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的Hashes,Hashes中,key為field1,并設(shè)value為s, 若字段field1存在,則無(wú)效hmset myhash field1"hello"field2 "world? ? ? 一次性設(shè)置多個(gè)字段刪hdel myhash field1? ? ? ? ? ? ? ? ? ? ? 刪除 myhash 鍵中字段名為 field1 的字段del myhash? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 刪除鍵改? hincrby myhash field1給field的值加1查hget myhash field1? ? ? ? ? ? ? ? ? ? ? 獲取鍵值為 myhash,字段為 field1 的值hlen myhash? ? ? ? ? ? ? ? ? ? ? ? ? ? 獲取myhash鍵的字段數(shù)量hexists myhash field1? ? ? ? ? ? ? ? ? 判斷 myhash 鍵中是否存在字段名為 field1 的字段hmget myhash field1 field2 field3? ? ? 一次性獲取多個(gè)字段hgetall myhash? ? ? ? ? ? ? ? ? ? ? ? ? 返回 myhash 鍵的所有字段及其值hkeys myhash? ? ? ? ? ? ? ? ? ? ? ? ? ? 獲取myhash 鍵中所有字段的名字hvals myhash? ? ? ? ? ? ? ? ? ? ? ? ? ? 獲取 myhash 鍵中所有字段的值
6.5 LIST(列表)
應(yīng)用場(chǎng)景消息隊(duì)列系統(tǒng)比如sina微博在Redis中我們的最新微博ID使用了常駐緩存,這是一直更新的。但是做了限制不能超過(guò)5000個(gè)ID,因此獲取ID的函數(shù)會(huì)一直詢問(wèn)Redis。只有在start/count參數(shù)超出了這個(gè)范圍的時(shí)候,才需要去訪問(wèn)數(shù)據(jù)庫(kù)。系統(tǒng)不會(huì)像傳統(tǒng)方式那樣“刷新”緩存,Redis實(shí)例中的信息永遠(yuǎn)是一致的。SQL數(shù)據(jù)庫(kù)(或是硬盤(pán)上的其他類型數(shù)據(jù)庫(kù))只是在用戶需要獲取“很遠(yuǎn)”的數(shù)據(jù)時(shí)才會(huì)被觸發(fā),而主頁(yè)或第一個(gè)評(píng)論頁(yè)是不會(huì)麻煩到硬盤(pán)上的數(shù)據(jù)庫(kù)了。微信朋友圈:127.0.0.1:6379>LPUSHwechat"today is nice day !"127.0.0.1:6379>LPUSHwechat"today is bad day !"127.0.0.1:6379>LPUSHwechat"today is good? day !"127.0.0.1:6379>LPUSHwechat"today is rainy? day !"127.0.0.1:6379>LPUSHwechat"today is friday !"[5,4,3,2,1]01234[e,d,c,b,a]01234127.0.0.1:6379>lrange wechat001)"today is friday !"127.0.0.1:6379>lrange wechat011)"today is friday !"2)"today is rainy? day !"127.0.0.1:6379>lrange wechat021)"today is friday !"2)"today is rainy? day !"3)"today is good? day !"127.0.0.1:6379>lrange wechat03127.0.0.1:6379>lrange wechat-2-11)"today is bad day !"2)"today is nice day !"-----------------增 lpush mykey a b? ? ? ? ? ? 若key不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的List,依次插入a,b, 若List類型的key存在,則插入value中l(wèi)pushx mykey2 e? ? ? ? ? ? 若key不存在,此命令無(wú)效, 若key存在,則插入value中l(wèi)insert mykey before a a1? 在 a 的前面插入新元素 a1linsert mykey after e e2? ? 在e 的后面插入新元素 e2rpush mykey a b? ? ? ? ? ? 在鏈表尾部先插入b,在插入arpushx mykey e? ? ? ? ? ? ? 若key存在,在尾部插入e,若key不存在,則無(wú)效rpoplpush mykey mykey2? ? ? 將mykey的尾部元素彈出,再插入到mykey2 的頭部(原子性的操作)刪del mykey? ? ? ? ? ? ? ? ? 刪除已有鍵 lrem mykey2a? ? ? ? ? ? ? 從頭部開(kāi)始找,按先后順序,值為a的元素,刪除數(shù)量為2個(gè),若存在第3個(gè),則不刪除ltrim mykey02從頭開(kāi)始,索引為0,1,2的3個(gè)元素,其余全部刪除改lset mykey1e? ? ? ? ? ? ? 從頭開(kāi)始,將索引為1的元素值,設(shè)置為新值 e,若索引越界,則返回錯(cuò)誤信息rpoplpush mykey mykey? ? ? 將 mykey 中的尾部元素移到其頭部查lrange mykey0-1取鏈表中的全部元素,其中0表示第一個(gè)元素,-1表示最后一個(gè)元素。lrange mykey02從頭開(kāi)始,取索引為0,1,2的元素lrange mykey00從頭開(kāi)始,取第一個(gè)元素,從第0個(gè)開(kāi)始,到第0個(gè)結(jié)束lpop mykey? ? ? ? ? ? ? ? ? 獲取頭部元素,并且彈出頭部元素,出棧lindex mykey6從頭開(kāi)始,獲取索引為6的元素 若下標(biāo)越界,則返回nil
6.6 SET 集合類型(join union)
應(yīng)用場(chǎng)景:案例:在微博應(yīng)用中,可以將一個(gè)用戶所有的關(guān)注人存在一個(gè)集合中,將其所有粉絲存在一個(gè)集合。Redis還為集合提供了求交集、并集、差集等操作,可以非常方便的實(shí)現(xiàn)如共同關(guān)注、共同喜好、二度好友等功能,對(duì)上面的所有集合操作,你還可以使用不同的命令選擇將結(jié)果返回給客戶端還是存集到一個(gè)新的集合中。127.0.0.1:6379> sadd lxl pg1 jnl baoqiang gsy alexsb(integer)5127.0.0.1:6379> sadd jnl baoqiang ms bbh yf wxg(integer)5127.0.0.1:6379> SUNION lx jnl1)"baoqiang"2)"yf"3)"bbh"4)"ms"5)"wxg"127.0.0.1:6379> SUNION lxl? jnl1)"gsy"2)"yf"3)"alexsb"4)"bbh"5)"jnl"6)"pg1"7)"baoqiang"8)"ms"9)"wxg"127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> SINTER lxl jnl1)"baoqiang"127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> SDIFF jnl lxl1)"wxg"2)"yf"3)"bbh"4)"ms"127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> SDIFF lxl jnl1)"jnl"2)"pg1"3)"gsy"4)"alexsb"增sadd myset a b c? 若key不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的set,依次插入a,b,若key存在,則插入value中,若a 在myset中已經(jīng)存在,則插入了 d 和 e 兩個(gè)新成員。刪spop myset? ? ? ? ? ? ? 尾部的b被移出,事實(shí)上b并不是之前插入的第一個(gè)或最后一個(gè)成員srem myset a d f? ? ? ? 若f不存在,移出 a、d,并返回2改smove myset myset2 a? ? ? ? 將a從 myset 移到 myset2,查sismember myset a? ? ? ? ? 判斷 a 是否已經(jīng)存在,返回值為 1 表示存在。smembers myset? ? ? ? ? 查看set中的內(nèi)容scard myset? ? ? ? ? ? 獲取Set 集合中元素的數(shù)量srandmember myset? ? ? 隨機(jī)的返回某一成員sdiff myset1 myset2 myset3? ? ? 1和2得到一個(gè)結(jié)果,拿這個(gè)集合和3比較,獲得每個(gè)獨(dú)有的值sdiffstore diffkey myset myset2 myset3? ? ? 3個(gè)集和比較,獲取獨(dú)有的元素,并存入diffkey 關(guān)聯(lián)的Set中sinter myset myset2 myset3? ? ? ? ? ? ? 獲得3個(gè)集合中都有的元素sinterstore interkey myset myset2 myset3? 把交集存入interkey 關(guān)聯(lián)的Set中sunion myset myset2 myset3? ? ? ? ? ? ? 獲取3個(gè)集合中的成員的并集sunionstore unionkey myset myset2 myset3? 把并集存入unionkey 關(guān)聯(lián)的Set中
6.7 SortedSet(有序集合)
應(yīng)用場(chǎng)景:排行榜應(yīng)用,取TOPN操作這個(gè)需求與上面需求的不同之處在于,前面操作以時(shí)間為權(quán)重,這個(gè)是以某個(gè)條件為權(quán)重,比如按頂?shù)拇螖?shù)排序,這時(shí)候就需要我們的sorted set出馬了,將你要排序的值設(shè)置成sorted set的score,將具體的數(shù)據(jù)設(shè)置成相應(yīng)的value,每次只需要執(zhí)行一條ZADD命令即可。127.0.0.1:6379>zadd topN0smlt0fskl0fshkl0lzlsfs0wdhbx0wxg(integer)6127.0.0.1:6379>ZINCRBYtopN100000smlt"100000"127.0.0.1:6379>ZINCRBYtopN10000fskl"10000"127.0.0.1:6379>ZINCRBYtopN1000000fshkl"1000000"127.0.0.1:6379>ZINCRBYtopN100lzlsfs"100"127.0.0.1:6379>ZINCRBYtopN10wdhbx"10"127.0.0.1:6379>ZINCRBYtopN100000000wxg"100000000"127.0.0.1:6379>ZREVRANGEtopN021)"wxg"2)"fshkl"3)"smlt"127.0.0.1:6379>ZREVRANGEtopN02withscores1)"wxg"2)"100000000"3)"fshkl"4)"1000000"5)"smlt"6)"100000"127.0.0.1:6379>增zadd myzset2"two"3"three"添加兩個(gè)分?jǐn)?shù)分別是2和3的兩個(gè)成員刪zrem myzset one two? ? ? ? ? ? ? ? 刪除多個(gè)成員變量,返回刪除的數(shù)量改zincrby myzset2one? ? ? ? ? ? ? ? 將成員 one 的分?jǐn)?shù)增加2,并返回該成員更新后的分?jǐn)?shù)查 zrange myzset0-1WITHSCORES返回所有成員和分?jǐn)?shù),不加WITHSCORES,只返回成員zrank myzset one? ? ? ? ? ? ? ? ? ? 獲取成員one在Sorted-Set中的位置索引值。0表示第一個(gè)位置zcard myzset? ? ? ? ? ? ? ? ? ? ? ? 獲取 myzset 鍵中成員的數(shù)量zcount myzset12獲取分?jǐn)?shù)滿足表達(dá)式1<=score<=2的成員的數(shù)量zscore myzset three? ? ? ? ? ? ? ? 獲取成員 three 的分?jǐn)?shù)zrangebyscore myzset12獲取分?jǐn)?shù)滿足表達(dá)式1<score<=2的成員#-inf 表示第一個(gè)成員,+inf最后一個(gè)成員#limit限制關(guān)鍵字#2? 3? 是索引號(hào)zrangebyscore myzset-inf+inf limit23返回索引是2和3的成員zremrangebyscore myzset12刪除分?jǐn)?shù)1<=score<=2的成員,并返回實(shí)際刪除的數(shù)量zremrangebyrank myzset01刪除位置索引滿足表達(dá)式0<=rank<=1的成員zrevrange myzset0-1WITHSCORES按位置索引從高到低,獲取所有成員和分?jǐn)?shù)#原始成員:位置索引從小到大one0two1#執(zhí)行順序:把索引反轉(zhuǎn)位置索引:從大到小? ? ? one1two0#輸出結(jié)果: two? onezrevrange myzset13獲取位置索引,為1,2,3的成員#相反的順序:從高到低的順序zrevrangebyscore myzset30獲取分?jǐn)?shù)3>=score>=0的成員并以相反的順序輸出zrevrangebyscore myzset40limit12獲取索引是1和2的成員,并反轉(zhuǎn)位置索引
7. 發(fā)布訂閱

need-to-insert-img
image.png
PUBLISH channel msg? ? 將信息 message 發(fā)送到指定的頻道 channelSUBSCRIBE channel [channel ...]? ? 訂閱頻道,可以同時(shí)訂閱多個(gè)頻道UNSUBSCRIBE [channel ...]? ? 取消訂閱指定的頻道,如果不指定頻道,則會(huì)取消訂閱所有頻道PSUBSCRIBE pattern [pattern ...]? ? 訂閱一個(gè)或多個(gè)符合給定模式的頻道,每個(gè)模式以 * 作為匹配符,比如 it* 匹配所? 有以 it 開(kāi)頭的頻道(it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 開(kāi)頭的頻道(news.it 、 news.global.today 等等),諸如此類PUNSUBSCRIBE [pattern [pattern ...]]? ? 退訂指定的規(guī)則,如果沒(méi)有參數(shù)則會(huì)退訂所有規(guī)則PUBSUB subcommand [argument [argument ...]]? ? 查看訂閱與發(fā)布系統(tǒng)狀態(tài)注意:使用發(fā)布訂閱模式實(shí)現(xiàn)的消息隊(duì)列,當(dāng)有客戶端訂閱channel后只能收到后續(xù)發(fā)布到該頻道的消息,之前發(fā)送的不會(huì)緩存,必須Provider和Consumer同時(shí)在線。發(fā)布訂閱例子:窗口1:127.0.0.1:6379> SUBSCRIBE baodi 窗口2:127.0.0.1:6379> PUBLISH baodi"jin tian zhen kaixin!"訂閱多頻道:窗口1:127.0.0.1:6379> PSUBSCRIBE wang*窗口2:127.0.0.1:6379> PUBLISH wangbaoqiang"jintian zhennanshou "
8、Redis事務(wù)
redis的事務(wù)是基于隊(duì)列實(shí)現(xiàn)的。mysql的事務(wù)是基于事務(wù)日志和鎖機(jī)制實(shí)現(xiàn)的。redis是樂(lè)觀鎖機(jī)制。開(kāi)啟事務(wù)功能時(shí)(multi)multi command1? ? ? command2command3command4exec discard4條語(yǔ)句作為一個(gè)組,并沒(méi)有真正執(zhí)行,而是被放入同一隊(duì)列中。如果,這是執(zhí)行discard,會(huì)直接丟棄隊(duì)列中所有的命令,而不是做回滾。exec當(dāng)執(zhí)行exec時(shí),對(duì)列中所有操作,要么全成功要么全失敗127.0.0.1:6379> set a bOK127.0.0.1:6379> MULTIOK127.0.0.1:6379> set a bQUEUED127.0.0.1:6379> set c dQUEUED127.0.0.1:6379> exec1)OK2)OK
9. redis樂(lè)觀鎖實(shí)現(xiàn)(模擬買票)
發(fā)布一張票set ticket 1窗口1:watch ticketmultiset ticket 0? ? ? 1---->0窗口2:multi set ticket 0 exec 窗口1:exec
10、 服務(wù)器管理命令
InfoClientlistClientkill ip:portconfigget*CONFIGRESETSTAT 重置統(tǒng)計(jì)CONFIGGET/SET 動(dòng)態(tài)修改DbsizeFLUSHALL 清空所有數(shù)據(jù)select1FLUSHDB 清空當(dāng)前庫(kù)MONITOR 監(jiān)控實(shí)時(shí)指令SHUTDOWN 關(guān)閉服務(wù)器關(guān)閉數(shù)據(jù)庫(kù):redis-cli-a root shutdown
11、redis(Master-Replicaset) *****
11.1 原理:
1. 副本庫(kù)通過(guò)slaveof 10.0.0.51 6379命令,連接主庫(kù),并發(fā)送SYNC給主庫(kù) 2. 主庫(kù)收到SYNC,會(huì)立即觸發(fā)BGSAVE,后臺(tái)保存RDB,發(fā)送給副本庫(kù)3. 副本庫(kù)接收后會(huì)應(yīng)用RDB快照4. 主庫(kù)會(huì)陸續(xù)將中間產(chǎn)生的新的操作,保存并發(fā)送給副本庫(kù)5. 到此,我們主復(fù)制集就正常工作了6. 再此以后,主庫(kù)只要發(fā)生新的操作,都會(huì)以命令傳播的形式自動(dòng)發(fā)送給副本庫(kù).7. 所有復(fù)制相關(guān)信息,從info信息中都可以查到.即使重啟任何節(jié)點(diǎn),他的主從關(guān)系依然都在.8. 如果發(fā)生主從關(guān)系斷開(kāi)時(shí),從庫(kù)數(shù)據(jù)沒(méi)有任何損壞,在下次重連之后,從庫(kù)發(fā)送PSYNC給主庫(kù)9. 主庫(kù)只會(huì)將從庫(kù)缺失部分的數(shù)據(jù)同步給從庫(kù)應(yīng)用,達(dá)到快速恢復(fù)主從的目的
11.2 主從數(shù)據(jù)一致性保證
min-slaves-to-write1min-slaves-max-lag3
11.3 主庫(kù)是否要開(kāi)啟持久化?
如果不開(kāi)有可能,主庫(kù)重啟操作,造成所有主從數(shù)據(jù)丟失!
12. 主從復(fù)制實(shí)現(xiàn)
1、環(huán)境:準(zhǔn)備兩個(gè)或兩個(gè)以上redis實(shí)例mkdir/data/638{0..2}配置文件示例:cat>>/data/6380/redis.conf<<EOFport6380daemonize yespidfile/data/6380/redis.pidloglevel noticelogfile"/data/6380/redis.log"dbfilename dump.rdbdir/data/6380requirepass123masterauth123EOFcat>>/data/6381/redis.conf<<EOFport6381daemonize yespidfile/data/6381/redis.pidloglevel noticelogfile"/data/6381/redis.log"dbfilename dump.rdbdir/data/6381requirepass123masterauth123EOFcat>>/data/6382/redis.conf<<EOFport6382daemonize yespidfile/data/6382/redis.pidloglevel noticelogfile"/data/6382/redis.log"dbfilename dump.rdbdir/data/6382requirepass123masterauth123EOF啟動(dòng):redis-server/data/6380/redis.confredis-server/data/6381/redis.confredis-server/data/6382/redis.conf主節(jié)點(diǎn):6380從節(jié)點(diǎn):6381、63822、開(kāi)啟主從:6381/6382命令行:redis-cli-p6381-a123SLAVEOF127.0.0.16380redis-cli-p6382-a123SLAVEOF127.0.0.163803、查詢主從狀態(tài) redis-cli-p6380-a123info replication redis-cli-p6381-a123info replication redis-cli-p6382-a123info replication
13 redis-sentinel(哨兵)
1、監(jiān)控2、自動(dòng)選主,切換(6381slaveof no one)3、2號(hào)從庫(kù)(6382)指向新主庫(kù)(6381)4、應(yīng)用透明5、自動(dòng)處理故障節(jié)點(diǎn)sentinel搭建過(guò)程mkdir/data/26380cd/data/26380vim sentinel.confport26380dir"/data/26380"sentinel monitor mymaster127.0.0.163801sentinel down-after-milliseconds mymaster5000sentinel auth-pass mymaster123啟動(dòng):[root@db0126380]# redis-sentinel/data/26380/sentinel.conf&>/tmp/sentinel.log&==============================如果有問(wèn)題:1、重新準(zhǔn)備1主2從環(huán)境2、kill掉sentinel進(jìn)程3、刪除sentinel目錄下的所有文件4、重新搭建sentinel======================================停主庫(kù)測(cè)試:[root@db01~]# redis-cli-p6380shutdown[root@db01~]# redis-cli-p6381info replication啟動(dòng)源主庫(kù)(6380),看狀態(tài)。Sentinel管理命令:redis-cli-p26380PING :返回 PONG 。SENTINELmasters :列出所有被監(jiān)視的主服務(wù)器SENTINELslaves<master name>SENTINELget-master-addr-by-name<master name>: 返回給定名字的主服務(wù)器的 IP 地址和端口號(hào)。SENTINELreset<pattern>: 重置所有名字和給定模式 pattern 相匹配的主服務(wù)器。SENTINELfailover<master name>: 當(dāng)主服務(wù)器失效時(shí), 在不詢問(wèn)其他 Sentinel 意見(jiàn)的情況下, 強(qiáng)制開(kāi)始一次自動(dòng)故障遷移。
14. redis cluster

image.png
14.1 介紹
高性能
1、在多分片節(jié)點(diǎn)中,將16384個(gè)槽位,均勻分布到多個(gè)分片節(jié)點(diǎn)中2、存數(shù)據(jù)時(shí),將key做crc16(key),然后和16384進(jìn)行取模,得出槽位值(0-16383之間)3、根據(jù)計(jì)算得出的槽位值,找到相對(duì)應(yīng)的分片節(jié)點(diǎn)的主節(jié)點(diǎn),存儲(chǔ)到相應(yīng)槽位上4、如果客戶端當(dāng)時(shí)連接的節(jié)點(diǎn)不是將來(lái)要存儲(chǔ)的分片節(jié)點(diǎn),分片集群會(huì)將客戶端連接切換至真正存儲(chǔ)節(jié)點(diǎn)進(jìn)行數(shù)據(jù)存儲(chǔ)
高可用:
在搭建集群時(shí),會(huì)為每一個(gè)分片的主節(jié)點(diǎn),對(duì)應(yīng)一個(gè)從節(jié)點(diǎn),實(shí)現(xiàn)slaveof的功能,同時(shí)當(dāng)主節(jié)點(diǎn)down,實(shí)現(xiàn)類似于sentinel的自動(dòng)failover的功能。1、redis會(huì)有多組分片構(gòu)成(3組)2、redis cluster 使用固定個(gè)數(shù)的slot存儲(chǔ)數(shù)據(jù)(一共16384slot)3、每組分片分得1/3 slot個(gè)數(shù)(0-5500? 5501-11000? 11001-16383)4、基于CRC16(key) % 16384 ====》值 (槽位號(hào))。
14.2 規(guī)劃、搭建過(guò)程:
6個(gè)redis實(shí)例,一般會(huì)放到3臺(tái)硬件服務(wù)器注:在企業(yè)規(guī)劃中,一個(gè)分片的兩個(gè)分到不同的物理機(jī),防止硬件主機(jī)宕機(jī)造成的整個(gè)分片數(shù)據(jù)丟失。端口號(hào):7000-7005
安裝集群插件
EPEL源安裝ruby支持yum install ruby rubygems-y使用國(guó)內(nèi)源gem sources-lgem sources-a http://mirrors.aliyun.com/rubygems/gem sources--removehttps://rubygems.org/gem sources-lgem install redis-v3.3.3
集群節(jié)點(diǎn)準(zhǔn)備
mkdir/data/700{0..5}cat>/data/7000/redis.conf<<EOFport7000daemonize yespidfile/data/7000/redis.pidloglevel noticelogfile"/data/7000/redis.log"dbfilename dump.rdbdir/data/7000protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOFcat>>/data/7001/redis.conf<<EOFport7001daemonize yespidfile/data/7001/redis.pidloglevel noticelogfile"/data/7001/redis.log"dbfilename dump.rdbdir/data/7001protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOFcat>>/data/7002/redis.conf<<EOFport7002daemonize yespidfile/data/7002/redis.pidloglevel noticelogfile"/data/7002/redis.log"dbfilename dump.rdbdir/data/7002protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOFcat>>/data/7003/redis.conf<<EOFport7003daemonize yespidfile/data/7003/redis.pidloglevel noticelogfile"/data/7003/redis.log"dbfilename dump.rdbdir/data/7003protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOFcat>>/data/7004/redis.conf<<EOFport7004daemonize yespidfile/data/7004/redis.pidloglevel noticelogfile"/data/7004/redis.log"dbfilename dump.rdbdir/data/7004protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOFcat>>/data/7005/redis.conf<<EOFport7005daemonize yespidfile/data/7005/redis.pidloglevel noticelogfile"/data/7005/redis.log"dbfilename dump.rdbdir/data/7005protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOF
啟動(dòng)節(jié)點(diǎn):
redis-server/data/7000/redis.conf redis-server/data/7001/redis.conf redis-server/data/7002/redis.conf redis-server/data/7003/redis.conf redis-server/data/7004/redis.conf redis-server/data/7005/redis.conf[root@db01 ~]# ps-ef |grep redisroot88541003:56?00:00:00redis-server*:7000[cluster]root88581003:56?00:00:00redis-server*:7001[cluster]root88601003:56?00:00:00redis-server*:7002[cluster]root88641003:56?00:00:00redis-server*:7003[cluster]root88661003:56?00:00:00redis-server*:7004[cluster]root88741003:56?00:00:00redis-server*:7005[cluster]
將節(jié)點(diǎn)加入集群管理
redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
集群狀態(tài)查看
集群主節(jié)點(diǎn)狀態(tài)redis-cli-p7000cluster nodes|grep master集群從節(jié)點(diǎn)狀態(tài)redis-cli-p7000cluster nodes|grep slave
14.3 集群節(jié)點(diǎn)管理
增加新的節(jié)點(diǎn)
mkdir/data/7006mkdir/data/7007cat>/data/7006/redis.conf<<EOFport7006daemonize yespidfile/data/7006/redis.pidloglevel noticelogfile"/data/7006/redis.log"dbfilename dump.rdbdir/data/7006protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOFcat>/data/7007/redis.conf<<EOFport7007daemonize yespidfile/data/7007/redis.pidloglevel noticelogfile"/data/7007/redis.log"dbfilename dump.rdbdir/data/7007protected-mode nocluster-enabled yescluster-config-file nodes.confcluster-node-timeout5000appendonly yesEOFredis-server/data/7006/redis.conf redis-server/data/7007/redis.conf
添加主節(jié)點(diǎn):
redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
轉(zhuǎn)移slot(重新分片)
redis-trib.rb reshard 127.0.0.1:7000
添加一個(gè)從節(jié)點(diǎn)
redis-trib.rb add-node --slave --master-id 8ff9ef5b78e6da62bd7b362e1fe190cba19ef5ae 127.0.0.1:7007 127.0.0.1:7000
14.4 刪除節(jié)點(diǎn)
將需要?jiǎng)h除節(jié)點(diǎn)slot移動(dòng)走
redis-trib.rb reshard 127.0.0.1:700049257f251824dd815bc7f31e1118b670365e861a 127.0.0.1:70060-1364 5461-6826 10923-122871365? ? ? 1366? ? 1365
刪除一個(gè)節(jié)點(diǎn)
刪除master節(jié)點(diǎn)之前首先要使用reshard移除master的全部slot,然后再刪除當(dāng)前節(jié)點(diǎn)redis-trib.rb del-node 127.0.0.1:7006 8ff9ef5b78e6da62bd7b362e1fe190cba19ef5ae---------------------設(shè)置redis最大內(nèi)存config set maxmemory 102400000---------------------
15.? redis的多API支持
python為例yum install-y python36 python3-Vyum install-y python36-pippip3 install redis pip3 install redis-py-cluster++++++++++++源碼方式+++++++++++++++https://redis.io/clients下載redis-py-master.zip安裝驅(qū)動(dòng):unzip redis-py-master.zipcd redis-py-masterpython3 setup.py installredis cluster的連接并操作(python2.7.2以上版本才支持redis cluster,我們選擇的是3.6)https://github.com/Grokzen/redis-py-cluster安裝redis-cluser的客戶端程序cd redis-py-cluster-unstablepython3 setup.py install+++++++++++++++++++++++++++++++++
對(duì)redis的單實(shí)例進(jìn)行連接操作
[root@db01~]# redis-server /data/6379/redis.conf python3>>>import redis>>>r=redis.StrictRedis(host='10.0.0.51',port=6379,db=0,password='123456')>>>r.set('oldboy','oldguo')>>>r.get('oldboy')
sentinel集群連接并操作
[root@db01~]# redis-server /data/6380/redis.conf[root@db01~]# redis-server /data/6381/redis.conf[root@db01~]# redis-server /data/6382/redis.conf [root@db01~]# redis-sentinel /data/26380/sentinel.conf &--------------------------------## 導(dǎo)入redis sentinel包>>>from redis.sentinel importSentinel##指定sentinel的地址和端口號(hào)>>>sentinel=Sentinel([('localhost',26380)],socket_timeout=0.1)##測(cè)試,獲取以下主庫(kù)和從庫(kù)的信息>>>sentinel.discover_master('mymaster')>>>sentinel.discover_slaves('mymaster')
配置讀寫(xiě)分離
#寫(xiě)節(jié)點(diǎn)>>>master=sentinel.master_for('mymaster',socket_timeout=0.1,password="123")#讀節(jié)點(diǎn)>>>slave=sentinel.slave_for('mymaster',socket_timeout=0.1,password="123")###讀寫(xiě)分離測(cè)試? key? ? >>>master.set('oldboy','123')>>>slave.get('oldboy')
python連接rediscluster集群測(cè)試
使用python3>>>fromredisclusterimportStrictRedisCluster>>>startup_nodes=[{"host":"127.0.0.1","port":"7000"},{"host":"127.0.0.1","port":"7001"},{"host":"127.0.0.1","port":"7002"}]### Note: decode_responses must be set to True when used with python3? >>>rc=StrictRedisCluster(startup_nodes=startup_nodes,decode_responses=True)>>>rc.set("foo","bar")True>>>print(rc.get("foo"))'bar'
16.一些概念
緩存穿透
概念訪問(wèn)一個(gè)不存在的key,緩存不起作用,請(qǐng)求會(huì)穿透到DB,流量大時(shí)DB會(huì)掛掉。解決方案采用布隆過(guò)濾器,使用一個(gè)足夠大的bitmap,用于存儲(chǔ)可能訪問(wèn)的key,不存在的key直接被過(guò)濾;訪問(wèn)key未在DB查詢到值,也將空值寫(xiě)進(jìn)緩存,但可以設(shè)置較短過(guò)期時(shí)間。
緩存雪崩
概念大量的key設(shè)置了相同的過(guò)期時(shí)間,導(dǎo)致在緩存在同一時(shí)刻全部失效,造成瞬時(shí)DB請(qǐng)求量大、壓力驟增,引起雪崩。解決方案可以給緩存設(shè)置過(guò)期時(shí)間時(shí)加上一個(gè)隨機(jī)值時(shí)間,使得每個(gè)key的過(guò)期時(shí)間分布開(kāi)來(lái),不會(huì)集中在同一時(shí)刻失效。
緩存擊穿
概念一個(gè)存在的key,在緩存過(guò)期的一刻,同時(shí)有大量的請(qǐng)求,這些請(qǐng)求都會(huì)擊穿到DB,造成瞬時(shí)DB請(qǐng)求量大、壓力驟增。解決方案在訪問(wèn)key之前,采用SETNX(set if not exists)來(lái)設(shè)置另一個(gè)短期key來(lái)鎖住當(dāng)前key的訪問(wèn),訪問(wèn)結(jié)束再刪除該短期key。
========================Redis END=======================
作者:MySQL_oldguo
鏈接:http://www.itdecent.cn/p/8af6177f4c23
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。