redis 基礎(chǔ)總結(jié)

redis簡(jiǎn)介:

官方鏈接:跳轉(zhuǎn)地址;中文官方鏈接:跳轉(zhuǎn)地址

Redis 是一個(gè)開(kāi)源(BSD許可)的扯俱,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng)些膨,它可以用作數(shù)據(jù)庫(kù)、緩存和消息中間件腕侄。 它支持多種類(lèi)型的數(shù)據(jù)結(jié)構(gòu)小泉,如 字符串(strings), 散列(hashes)冕杠, 列表(lists)微姊, 集合(sets), 有序集合(sorted sets) 與范圍查詢分预, bitmaps兢交, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢。 Redis 內(nèi)置了 復(fù)制(replication)笼痹,LUA腳本(Lua scripting)配喳, LRU驅(qū)動(dòng)事件(LRU eviction),事務(wù)(transactions) 和不同級(jí)別的 磁盤(pán)持久化(persistence)凳干, 并通過(guò) Redis哨兵(Sentinel)和自動(dòng) 分區(qū)(Cluster)提供高可用性(high availability)晴裹。

可以對(duì)這些類(lèi)型運(yùn)行原子操作,例如附加到字符串;遞增哈希值;將元素推送到列表中;計(jì)算集合交集救赐,并集和差異;或者在排序集中獲得排名最高的成員涧团。

為了實(shí)現(xiàn)其出色的性能,Redis使用內(nèi)存數(shù)據(jù)集净响。根據(jù)您的使用情況,您可以通過(guò)每隔一段時(shí)間將數(shù)據(jù)集轉(zhuǎn)儲(chǔ)到磁盤(pán)或通過(guò)將每個(gè)命令附加到日志來(lái)保留它喳瓣。如果您只需要功能豐富的網(wǎng)絡(luò)內(nèi)存緩存馋贤,則可以選擇禁用持久性。

Redis還支持簡(jiǎn)單到設(shè)置的主從異步復(fù)制畏陕,具有非撑渑遥快速的非阻塞第一次同步,自動(dòng)重新連接以及在網(wǎng)絡(luò)分割上的部分重新同步惠毁。

其他功能包括:

  • 事物
  • 發(fā)布/訂閱
  • Lua腳本
  • 設(shè)置key的生存時(shí)間
  • LRU驅(qū)逐key(更新緩存)
  • 自動(dòng)故障轉(zhuǎn)移

Redis是用ANSI C編寫(xiě)的犹芹,適用于大多數(shù)POSIX系統(tǒng),如Linux鞠绰,* BSD腰埂,OS X,沒(méi)有外部依賴性蜈膨。Linux和OS X是Redis開(kāi)發(fā)和測(cè)試的兩個(gè)操作系統(tǒng)屿笼,我們建議使用Linux進(jìn)行部署牺荠。Windows版本沒(méi)有官方支持,但Microsoft開(kāi)發(fā)并維護(hù)了Redis的Win-64端口驴一。

redis單機(jī)版使用

下載鏈接:跳轉(zhuǎn)地址

下載以及安裝

1.安裝單機(jī)版參考redis官網(wǎng)

$ wget http://download.redis.io/releases/redis-5.0.0.tar.gz
$ tar xzf redis-5.0.0.tar.gz
$ cd redis-5.0.0
$ make

2.啟動(dòng)默認(rèn)安裝好的redis服務(wù)

$ src/redis-server

3.查看redis默認(rèn)配置信息:

$ src/redis-cli info

添加認(rèn)證以及后臺(tái)啟動(dòng)模式

修改redis配置redis.conf文件休雌,修改以下內(nèi)容即可

daemonize yes
requirepass YouPassword

重啟redis服務(wù)并指定配置文件,即生效

$ src/redis-server redis.conf

查看redis信息

$ src/redis-cli -a admin -p 6379 info
# Server
redis_version:4.0.11
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:1d679a1d2d6b6fc8
**redis_mode:standalone**
os:Darwin 16.7.0 x86_64
arch_bits:64
multiplexing_api:kqueue
atomicvar_api:atomic-builtin
gcc_version:4.2.1
process_id:27355
run_id:15e44fc5b4b0da7a879fabdb0e4fdccf3d514389
**tcp_port:6379**
uptime_in_seconds:23
uptime_in_days:0
hz:10
lru_clock:13288401
executable:/Users/xiaodongsun/Downloads/redis-4.0.11/src/redis-server
**config_file:/Users/xiaodongsun/Downloads/redis-4.0.11/redis.conf**

# Clients
**connected_clients:1**
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

# Memory
**used_memory:1032992**
used_memory_human:1008.78K
**used_memory_rss:1601536**
used_memory_rss_human:1.53M
**used_memory_peak:1032992**
used_memory_peak_human:1008.78K
used_memory_peak_perc:105.32%
used_memory_overhead:1030478
used_memory_startup:980848
used_memory_dataset:2514
used_memory_dataset_perc:4.82%
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
**maxmemory:0**
maxmemory_human:0B
maxmemory_policy:noeviction
**mem_fragmentation_ratio:1.55**
mem_allocator:libc
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1540015034
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
**aof_enabled:0**
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats
total_connections_received:2
total_commands_processed:1
instantaneous_ops_per_sec:0
total_net_input_bytes:53
total_net_output_bytes:39
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:0
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
**role:master**
connected_slaves:0
master_replid:bb6813b6a6a62c3529b609fd154115da8a21d51a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:0.01
used_cpu_user:0.01
used_cpu_sys_children:0.00
used_cpu_user_children:0.00

# Cluster
**cluster_enabled:0**

# Keyspace

redis常用數(shù)據(jù)類(lèi)型

redis最為常用的數(shù)據(jù)類(lèi)型主要有以下:

- String 
- Hash
- List
- Set
- Sorted Set
- pub/sub
- Transactions

String

Strings 數(shù)據(jù)結(jié)構(gòu)是簡(jiǎn)單的key-value類(lèi)型肝断,value其實(shí)不僅是String杈曲,也可以是數(shù)字.
常用命令: set,get,decr,incr(原子遞增),mget,mset,getset等。

127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379>
127.0.0.1:6379> SET string root
OK
127.0.0.1:6379> GET string
"root"
127.0.0.1:6379> SET string admin #重新覆蓋相同key的value
OK
127.0.0.1:6379> GET string
"admin"
127.0.0.1:6379> SET count 1
OK
127.0.0.1:6379> INCR count #原子遞增
(integer) 2
127.0.0.1:6379> GET count
"2"
127.0.0.1:6379> DECR count #原子遞減
(integer) 1
127.0.0.1:6379> GET count
"1"
127.0.0.1:6379> GETSET test getset #將key對(duì)應(yīng)的值重新賦值胸懈,并返回key對(duì)應(yīng)的原有值
"1"
127.0.0.1:6379> MGET test count string #MEGT/MSET一次性獲取或存儲(chǔ)多個(gè)key對(duì)應(yīng)的值
1) "getset"
2) "1"
3) "admin"

應(yīng)用場(chǎng)景:String是最常用的一種數(shù)據(jù)類(lèi)型担扑,普通的key/ value 存儲(chǔ)都可以歸為此類(lèi).即可以完全實(shí)現(xiàn)目前 Memcached 的功能,并且效率更高箫荡。還可以享受Redis的定時(shí)持久化魁亦,操作日志及 Replication等功能。除了提供與 Memcached 一樣的get羔挡、set洁奈、incr、decr 等操作外绞灼,Redis還提供了下面一些操作:

  • 獲取字符串長(zhǎng)度
  • 往字符串a(chǎn)ppend內(nèi)容
  • 設(shè)置和獲取字符串的某一段內(nèi)容
  • 設(shè)置及獲取字符串的某一位(bit)
  • 批量設(shè)置一系列字符串的內(nèi)容

實(shí)現(xiàn)方式:

String在redis內(nèi)部存儲(chǔ)默認(rèn)就是一個(gè)字符串利术,被redisObject所引用,當(dāng)遇到incr,decr等操作時(shí)會(huì)轉(zhuǎn)成數(shù)值型進(jìn)行計(jì)算低矮,此時(shí)redisObject的encoding字段為int印叁。

修改或查詢鍵空間

有些指令不是針對(duì)任何具體的類(lèi)型定義的,而是用于和整個(gè)鍵空間交互的军掂。因此轮蜕,它們可被用于任何類(lèi)型的鍵。

使用EXISTS命令返回1或0標(biāo)識(shí)給定key的值是否存在蝗锥,使用DEL命令可以刪除key對(duì)應(yīng)的值跃洛,DEL命令返回1或0標(biāo)識(shí)值是被刪除(值存在)或者沒(méi)被刪除(key對(duì)應(yīng)的值不存在)。

127.0.0.1:6379> EXISTS count #判斷是否存在該key
(integer) 1
127.0.0.1:6379> DEL count #刪除鍵值對(duì)
(integer) 1
127.0.0.1:6379> TYPE string #key對(duì)應(yīng)的值的存儲(chǔ)類(lèi)型
string

redis超時(shí):數(shù)據(jù)在限定時(shí)間內(nèi)存活

127.0.0.1:6379> EXPIRE string 20 #為已經(jīng)存在的key設(shè)置存活時(shí)間
(integer) 1
127.0.0.1:6379> TTL string #TTL命令用來(lái)查看key對(duì)應(yīng)的值剩余存活時(shí)間终议。
(integer) 14
127.0.0.1:6379> SET expire 10ms ex 60 #設(shè)置鍵值對(duì)的時(shí)候汇竭,指定存活時(shí)間
OK
127.0.0.1:6379> TTL expire
(integer) 53

Lists

Redis lists基于Linked Lists實(shí)現(xiàn)。這意味著即使在一個(gè)list中有數(shù)百萬(wàn)個(gè)元素穴张,在頭部或尾部添加一個(gè)元素的操作细燎,其時(shí)間復(fù)雜度也是常數(shù)級(jí)別的。用LPUSH 命令在十個(gè)元素的list頭部添加新元素皂甘,和在千萬(wàn)元素list頭部添加新元素的速度相同玻驻。

那么,壞消息是什么偿枕?在數(shù)組實(shí)現(xiàn)的list中利用索引訪問(wèn)元素的速度極快击狮,而同樣的操作在linked list實(shí)現(xiàn)的list上沒(méi)有那么快佛析。
Redis Lists用linked list實(shí)現(xiàn)的原因是:對(duì)于數(shù)據(jù)庫(kù)系統(tǒng)來(lái)說(shuō),至關(guān)重要的特性是:能非常快的在很大的列表上添加元素。另一個(gè)重要因素是并思,正如你將要看到的:Redis lists能在常數(shù)時(shí)間取得常數(shù)長(zhǎng)度。

如果快速訪問(wèn)集合元素很重要膘茎,建議使用可排序集合(sorted sets)】崾模可排序集合我們會(huì)隨后介紹披坏。

常用命令:lpush,rpush,lpop,rpop,lrange等。

127.0.0.1:6379> LSET lists 0 a #當(dāng)key不存在報(bào)錯(cuò)
(error) ERR no such key
127.0.0.1:6379> RPUSH lists a #向list左邊添加一個(gè)新元素盐数,若key不存在則新建一個(gè)key
(integer) 1
127.0.0.1:6379> keys *
1) "lists"
127.0.0.1:6379> LPUSH lists A
(integer) 2
127.0.0.1:6379> LINDEX lists 0
"A"
127.0.0.1:6379> LINDEX lists 1
"a"
127.0.0.1:6379> LRANGE lists 0 -1 #LRANGE 帶有兩個(gè)索引棒拂,一定范圍的第一個(gè)和最后一個(gè)元素。這兩個(gè)索引都可以為負(fù)來(lái)告知Redis從尾部開(kāi)始計(jì)數(shù)玫氢,因此-1表示最后一個(gè)元素帚屉,-2表示list中的倒數(shù)第二個(gè)元素,以此類(lèi)推漾峡。
1) "A"
2) "a"
27.0.0.1:6379> RPUSH lists b c d e f #一次向list存入多個(gè)值
(integer) 7
127.0.0.1:6379> LRANGE lists 0 -1
1) "A"
2) "a"
3) "b"
4) "c"
5) "d"
6) "e"
7) "f"
127.0.0.1:6379> RPOP lists #它從list中刪除元素并同時(shí)返回刪除的值攻旦。可以在左邊或右邊操作生逸。(抽獎(jiǎng))
"f"
127.0.0.1:6379> RPOP lists
"d"
127.0.0.1:6379> LPOP lists
"A"
127.0.0.1:6379> LPOP lists
"a"
127.0.0.1:6379> LPOP lists #在這最后 列表中的命令序列是空的牢屋,沒(méi)有更多的元素可以被彈出。
(nil)
127.0.0.1:6379> LTRIM list 0 2 #可以使用LTRIM把list從左邊截取指定長(zhǎng)度
OK
127.0.0.1:6379> LRANGE list 0 -1
1) "b"
2) "c"
3) "d"
127.0.0.1:6379> LLEN list #list長(zhǎng)度
(integer) 3

應(yīng)用場(chǎng)景:
Redis list的應(yīng)用場(chǎng)景非常多槽袄,也是Redis最重要的數(shù)據(jù)結(jié)構(gòu)之一烙无,比如twitter的關(guān)注列表,粉絲列表等都可以用Redis的list結(jié)構(gòu)來(lái)實(shí)現(xiàn)遍尺。

Lists 就是鏈表截酷,相信略有數(shù)據(jù)結(jié)構(gòu)知識(shí)的人都應(yīng)該能理解其結(jié)構(gòu)。使用Lists結(jié)構(gòu)狮鸭,我們可以輕松地實(shí)現(xiàn)最新消息排行等功能合搅。Lists的另一個(gè)應(yīng)用就是消息隊(duì)列多搀,
可以利用Lists的PUSH操作歧蕉,將任務(wù)存在Lists中,然后工作線程再用POP操作將任務(wù)取出進(jìn)行執(zhí)行康铭。Redis還提供了操作Lists中某一段的api惯退,你可以直接查詢,刪除Lists中某一段的元素从藤。

實(shí)現(xiàn)方式:

Redis list的實(shí)現(xiàn)為一個(gè)雙向鏈表催跪,即可以支持反向查找和遍歷锁蠕,更方便操作,不過(guò)帶來(lái)了部分額外的內(nèi)存開(kāi)銷(xiāo)懊蒸,Redis內(nèi)部的很多實(shí)現(xiàn)荣倾,包括發(fā)送緩沖隊(duì)列等也都是用的這個(gè)數(shù)據(jù)結(jié)構(gòu)。

Hash

Redis hash 看起來(lái)就像一個(gè) “hash” 的樣子骑丸,由鍵值對(duì)組成舌仍,Hash 便于表示 objects,實(shí)際上通危,你可以放入一個(gè) hash 的域數(shù)量實(shí)際上沒(méi)有限制(除了可用內(nèi)存以外)铸豁。所以,你可以在你的應(yīng)用中以不同的方式使用 hash菊碟。值得注意的是节芥,小的 hash 被用特殊方式編碼,非常節(jié)約內(nèi)存逆害。hash指令的完整列表头镊,常用命令:hget,hset,hgetall 等。

127.0.0.1:6379> HMSET user:01 username admin birthyear 1995 verified 1 #設(shè)置 hash 中的多個(gè)域
OK
127.0.0.1:6379> HGET user:01 username #取回單個(gè)域
"admin"
127.0.0.1:6379> HGET user:01 birthyear
"1995"
127.0.0.1:6379> HMGET user:01 username verified #取回指定的多個(gè)域忍燥,類(lèi)似MGET
1) "admin"
2) "1"
127.0.0.1:6379> HGETALL user:01 #返回一系列值
1) "username"
2) "admin"
3) "birthyear"
4) "1995"
5) "verified"
6) "1"
127.0.0.1:6379> HEXISTS user:01 username #是否存在
(integer) 1
127.0.0.1:6379> HKEYS user:01 #所有key
1) "username"
2) "birthyear"
3) "verified"
127.0.0.1:6379> HSTRLEN user:01 username #字符長(zhǎng)度
(integer) 5
127.0.0.1:6379> HVALS user:01 #所有值
1) "admin"
2) "1995"
3) "1"
127.0.0.1:6379> HSETNX user:01 sex man #增加鍵值域
(integer) 1
127.0.0.1:6379> HLEN user:01 #key中存儲(chǔ)的哈希中包含的字段數(shù)
(integer) 4
127.0.0.1:6379> HINCRBY user:01 birthyear -1 #執(zhí)行遞增和遞減操作
(integer) 1994
127.0.0.1:6379> HINCRBYFLOAT user:01 birthyear 0.5 #執(zhí)行浮點(diǎn)遞增和遞減操作
"1994.5"
127.0.0.1:6379> HSCAN user:01 0 #迭代集合
1) "0"
2) 1) "username"
   2) "admin"
   3) "birthyear"
   4) "1994.5"
   5) "verified"
   6) "1"
   7) "sex"
   8) "man"

應(yīng)用場(chǎng)景:在Memcached中拧晕,我們經(jīng)常將一些結(jié)構(gòu)化的信息打包成HashMap,在客戶端序列化后存儲(chǔ)為一個(gè)字符串的值梅垄,比如用戶的昵稱(chēng)厂捞、年齡、性別队丝、積分等靡馁,這時(shí)候在需要修改其中某一項(xiàng)時(shí),通常需要將所有值取出反序列化后机久,修改某一項(xiàng)的值臭墨,再序列化存儲(chǔ)回去。這樣不僅增大了開(kāi)銷(xiāo)膘盖,也不適用于一些可能并發(fā)操作的場(chǎng)合(比如兩個(gè)并發(fā)的操作都需要修改積分)胧弛。而Redis的Hash結(jié)構(gòu)可以使你像在數(shù)據(jù)庫(kù)中Update一個(gè)屬性一樣只修改某一項(xiàng)屬性值。

簡(jiǎn)單舉個(gè)實(shí)例來(lái)描述下Hash的應(yīng)用場(chǎng)景侠畔,比如我們要存儲(chǔ)一個(gè)用戶信息對(duì)象數(shù)據(jù)结缚,包含以下信息:

用戶ID為查找的key,存儲(chǔ)的value用戶對(duì)象包含姓名软棺,年齡红竭,生日等信息,如果用普通的key/value結(jié)構(gòu)來(lái)存儲(chǔ),主要有以下2種存儲(chǔ)方式:

第一種方式將用戶ID作為查找key,把其他信息封裝成一個(gè)對(duì)象以序列化的方式存儲(chǔ)茵宪,這種方式的缺點(diǎn)是最冰,增加了序列化/反序列化的開(kāi)銷(xiāo),并且在需要修改其中一項(xiàng)信息時(shí)稀火,需要把整個(gè)對(duì)象取回暖哨,并且修改操作需要對(duì)并發(fā)進(jìn)行保護(hù),引入CAS等復(fù)雜問(wèn)題凰狞。

第二種方法是這個(gè)用戶信息對(duì)象有多少成員就存成多少個(gè)key-value對(duì)兒鹿蜀,用用戶ID+對(duì)應(yīng)屬性的名稱(chēng)作為唯一標(biāo)識(shí)來(lái)取得對(duì)應(yīng)屬性的值,雖然省去了序列化開(kāi)銷(xiāo)和并發(fā)問(wèn)題服球,但是用戶ID為重復(fù)存儲(chǔ)茴恰,如果存在大量這樣的數(shù)據(jù),內(nèi)存浪費(fèi)還是非痴缎埽可觀的往枣。

那么Redis提供的Hash很好的解決了這個(gè)問(wèn)題,Redis的Hash實(shí)際是內(nèi)部存儲(chǔ)的Value為一個(gè)HashMap粉渠,并提供了直接存取這個(gè)Map成員的接口分冈。也就是說(shuō),Key仍然是用戶ID, value是一個(gè)Map霸株,這個(gè)Map的key是成員的屬性名雕沉,value是屬性值,這樣對(duì)數(shù)據(jù)的修改和存取都可以直接通過(guò)其內(nèi)部Map的Key(Redis里稱(chēng)內(nèi)部Map的key為field), 也就是通過(guò) key(用戶ID) + field(屬性標(biāo)簽) 就可以操作對(duì)應(yīng)屬性數(shù)據(jù)了去件,既不需要重復(fù)存儲(chǔ)數(shù)據(jù)坡椒,也不會(huì)帶來(lái)序列化和并發(fā)修改控制的問(wèn)題。很好的解決了問(wèn)題尤溜。

這里同時(shí)需要注意倔叼,Redis提供了接口(hgetall)可以直接取到全部的屬性數(shù)據(jù),但是如果內(nèi)部Map的成員很多,那么涉及到遍歷整個(gè)內(nèi)部Map的操作宫莱,由于Redis單線程模型的緣故丈攒,這個(gè)遍歷操作可能會(huì)比較耗時(shí),而另其它客戶端的請(qǐng)求完全不響應(yīng)授霸,這點(diǎn)需要格外注意巡验。

實(shí)現(xiàn)方式:

Redis Hash對(duì)應(yīng)Value內(nèi)部實(shí)際就是一個(gè)HashMap,實(shí)際這里會(huì)有2種不同實(shí)現(xiàn)碘耳,這個(gè)Hash的成員比較少時(shí)Redis為了節(jié)省內(nèi)存會(huì)采用類(lèi)似一維數(shù)組的方式來(lái)緊湊存儲(chǔ)显设,而不會(huì)采用真正的HashMap結(jié)構(gòu),對(duì)應(yīng)的value redisObject的encoding為zipmap,當(dāng)成員數(shù)量增大時(shí)會(huì)自動(dòng)轉(zhuǎn)成真正的HashMap,此時(shí)encoding為ht藏畅。

Set

Redis Set 是 String 的無(wú)序排列敷硅。SADD 指令把新的元素添加到 set 中。對(duì) set 也可做一些其他的操作愉阎,比如測(cè)試一個(gè)給定的元素是否存在绞蹦,對(duì)不同 set 取交集,并集或差榜旦,等等幽七。常用命令:
sadd,spop,smembers,sunion 等。更多命令參考

127.0.0.1:6379> SADD array 1 a a b #新的元素添加到 set 中
(integer) 3
127.0.0.1:6379> SMEMBERS array #顯示set成員,去重并且無(wú)序排列
1) "1"
2) "b"
3) "a"
127.0.0.1:6379> SISMEMBER array a #檢測(cè)特定的元素是否存在
(integer) 1
127.0.0.1:6379
127.0.0.1:6379> SADD news:1000:tags 1 2 5 77
(integer) 4
127.0.0.1:6379> SADD tag:1:news 1000
(integer) 1
127.0.0.1:6379> SADD tag:2:news 1000
(integer) 1
127.0.0.1:6379> SADD tag:5:news 1000
(integer) 1
127.0.0.1:6379> SADD tag:77:news 1000
(integer) 1
127.0.0.1:6379> SMEMBERS news:1000:tags
1) "1"
2) "2"
3) "5"
4) "77"
127.0.0.1:6379> SINTER tag:1:news tag:2:news #獲取不同 set 的交集
1) "1000"
127.0.0.1:6379> SDIFF tag:2:news tag:77:news #交集
(empty list or set)
127.0.0.1:6379> SUNION array tag:2:news #并集
1) "1"
2) "a"
3) "1000"
4) "2"
5) "3"
6) "b"
127.0.0.1:6379> SSCAN array 0 #迭代集合中的元素
1) "0"
2) 1) "1"
   2) "2"
   3) "3"
   4) "a"
   5) "b"
127.0.0.1:6379> sadd deck C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 CJ CQ CK D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 DJ DQ DK H1 H2 H3 H4 H5 H6 H7 H8 H9 H10 HJ HQ HK S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 SJ SQ SK #模擬撲克牌
(integer) 52
127.0.0.1:6379> sunionstore game:1:deck deck #對(duì)多個(gè)集合取并集溅呢,并把結(jié)果存入另一個(gè) set 中
(integer) 52
127.0.0.1:6379> keys *
1) "news:1000:tags"
2) "tag:2:news"
3) "tag:5:news"
4) "array"
5) "tag:1:news"
6) "game:1:deck"
7) "deck"
8) "tag:77:news"
127.0.0.1:6379> SPOP game:1:deck #隨機(jī)從set集合中獲取一個(gè)值(發(fā)牌)
"S5"
127.0.0.1:6379> SPOP game:1:deck
"H9"
127.0.0.1:6379> SCARD game:1:deck #set里剩余元素?cái)?shù)量
(integer) 50
127.0.0.1:6379> SRANDMEMBER game:1:deck #獲取隨機(jī)元素而不從集合中刪除它
"D5"

應(yīng)用場(chǎng)景:Redis set對(duì)外提供的功能與list類(lèi)似是一個(gè)列表的功能澡屡,特殊之處在于set是可以自動(dòng)排重的,當(dāng)你需要存儲(chǔ)一個(gè)列表數(shù)據(jù)咐旧,又不希望出現(xiàn)重復(fù)數(shù)據(jù)時(shí)驶鹉,set是一個(gè)很好的選擇,并且set提供了判斷某個(gè)成員是否在一個(gè)set集合內(nèi)的重要接口铣墨,這個(gè)也是list所不能提供的室埋。

Sets 集合的概念就是一堆不重復(fù)值的組合。利用Redis提供的Sets數(shù)據(jù)結(jié)構(gòu)伊约,可以存儲(chǔ)一些集合性的數(shù)據(jù)姚淆,比如在微博應(yīng)用中,可以將一個(gè)用戶所有的關(guān)注人存在一個(gè)集合中屡律,將其所有粉絲存在一個(gè)集合腌逢。Redis還為集合提供了求交集、并集超埋、差集等操作搏讶,可以非常方便的實(shí)現(xiàn)如共同關(guān)注、共同喜好霍殴、二度好友等功能窍蓝,對(duì)上面的所有集合操作,你還可以使用不同的命令選擇將結(jié)果返回給客戶端還是存集到一個(gè)新的集合中繁成。

實(shí)現(xiàn)方式:

set 的內(nèi)部實(shí)現(xiàn)是一個(gè)value永遠(yuǎn)為null的HashMap吓笙,實(shí)際就是通過(guò)計(jì)算hash的方式來(lái)快速排重的,這也是set能提供判斷一個(gè)成員是否在集合內(nèi)的原因巾腕。

Sorted Set

Sorted sets是一種數(shù)據(jù)類(lèi)型面睛,類(lèi)似于Set和Hash之間的混合。與集合一樣尊搬,有序集合由唯一的叁鉴,非重復(fù)的字符串元素組成,因此在某種意義上佛寿,有序集合也是一個(gè)集合幌墓。

排序集合中的元素按順序排列(因此它們不是根據(jù)請(qǐng)求排序的但壮,順序是用于表示排序集合的數(shù)據(jù)結(jié)構(gòu)的特性)。它們按照以下規(guī)則訂購(gòu):

  • 如果A和B是兩個(gè)具有不同分?jǐn)?shù)的元素常侣,那么A> B蜡饵,如果A.score是> B.score。
  • 如果A和B具有完全相同的score胳施,那么如果A字符串在字典上大于B字符串溯祸,則A> B.A和B字符串不能相等,因?yàn)橛行蚣挥形ㄒ辉亍?/li>
127.0.0.1:6379> zadd hackers 1940 "Alan Kay"
(integer) 1
127.0.0.1:6379> zadd hackers 1957 "Sophie Wilson"
(integer) 1
127.0.0.1:6379> zadd hackers 1953 "Richard Stallman"
(integer) 1
127.0.0.1:6379> ZRANGE hackers 0 -1 #通過(guò)索引區(qū)間返回有序集合成指定區(qū)間內(nèi)的成員;返回按出生年份排序的黑客列表,0和-1表示從元素索引0到最后一個(gè)元素
1) "Alan Kay"
2) "Richard Stallman"
3) "Sophie Wilson"
127.0.0.1:6379> ZREVRANGE hackers 0 -1 #以相反的方式
1) "Sophie Wilson"
2) "Richard Stallman"
3) "Alan Kay"
127.0.0.1:6379> ZRANGE hackers 0 -1 WITHSCORES #通過(guò)索引區(qū)間返回有序集合成指定區(qū)間內(nèi)的成員以及scores
1) "Alan Kay"
2) "1940"
3) "Richard Stallman"
4) "1953"
5) "Sophie Wilson"
6) "1957"
127.0.0.1:6379> ZRANGEBYSCORE hackers -inf 1950 #所有出生到1950年的人
1) "Alan Kay"
127.0.0.1:6379> ZREMRANGEBYSCORE hackers 1940 1960 #從排序集中刪除1940年到1960年間出生的所有黑客,并返回已刪除元素的數(shù)量舞肆。
(integer) 3
127.0.0.1:6379> ZRANK hackers "Alan Kay" #詢問(wèn)有序元素集中元素的位置
(integer) 0
127.0.0.1:6379> ZRANK hackers "Sophie Wilson"
(integer) 1
127.0.0.1:6379> zadd hackers 0 "Alan Kay" 0 "Sophie Wilson" 0 "Richard Stallman" 0 "Anita Borg" 0 "Yukihiro Matsumoto" 0 "Hedy Lamarr" 0 "Claude Shannon" 0 "Linus Torvalds" 0 "Alan Turing" #插入了相同的相同分?jǐn)?shù),按字典順序獲取,
(integer) 9
127.0.0.1:6379> ZRANGE hackers 0 -1 #由于排序集排序規(guī)則焦辅,它們已經(jīng)按字典順序排序:
1) "Alan Kay"
2) "Alan Turing"
3) "Anita Borg"
4) "Claude Shannon"
5) "Hedy Lamarr"
6) "Linus Torvalds"
7) "Richard Stallman"
8) "Sophie Wilson"
9) "Yukihiro Matsumoto"
127.0.0.1:6379> ZRANGEBYLEX hackers [B [P #使用ZRANGEBYLEX我們可以要求詞典范圍
1) "Claude Shannon"
2) "Hedy Lamarr"
3) "Linus Torvalds"

使用場(chǎng)景:Redis sorted set的使用場(chǎng)景與set類(lèi)似,區(qū)別是set不是自動(dòng)有序的椿胯,而sorted set可以通過(guò)用戶額外提供一個(gè)優(yōu)先級(jí)(score)的參數(shù)來(lái)為成員排序筷登,并且是插入有序的,即自動(dòng)排序哩盲。當(dāng)你需要一個(gè)有序的并且不重復(fù)的集合列表仆抵,那么可以選擇sorted set數(shù)據(jù)結(jié)構(gòu),比如twitter 的public timeline可以以發(fā)表時(shí)間作為score來(lái)存儲(chǔ)种冬,這樣獲取時(shí)就是自動(dòng)按時(shí)間排好序的镣丑。

另外還可以用Sorted Sets來(lái)做帶權(quán)重的隊(duì)列,比如普通消息的score為1娱两,重要消息的score為2莺匠,然后工作線程可以選擇按score的倒序來(lái)獲取工作任務(wù)。讓重要的任務(wù)優(yōu)先執(zhí)行十兢。

實(shí)現(xiàn)方式:

Redis sorted set的內(nèi)部使用HashMap和跳躍表(SkipList)來(lái)保證數(shù)據(jù)的存儲(chǔ)和有序趣竣,HashMap里放的是成員到score的映射,而跳躍表里存放的是所有的成員旱物,排序依據(jù)是HashMap里存的score,使用跳躍表的結(jié)構(gòu)可以獲得比較高的查找效率遥缕,并且在實(shí)現(xiàn)上比較簡(jiǎn)單。

Pub/Sub

Pub/Sub 從字面上理解就是發(fā)布(Publish)與訂閱(Subscribe)宵呛,在Redis中单匣,你可以設(shè)定對(duì)某一個(gè)key值進(jìn)行消息發(fā)布及消息訂閱,當(dāng)一個(gè)key值上進(jìn)行了消息發(fā)布后宝穗,所有訂閱它的客戶端都會(huì)收到相應(yīng)的消息户秤。這一功能最明顯的用法就是用作實(shí)時(shí)消息系統(tǒng),比如普通的即時(shí)聊天逮矛,群聊等功能鸡号。

客戶端1:

127.0.0.1:6379> SUBSCRIBE redisChat #創(chuàng)建了訂閱頻道名為 redisChat,訂閱者就能接收到消息。
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
# 訂閱者的客戶端會(huì)顯示如下消息
3) (integer) 1
1) "message"
2) "redisChat"
3) "Redis is a great caching technique"
1) "message"
2) "redisChat"
3) "hello redis"

客戶端2:

127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique" #在同一個(gè)頻道 redisChat 發(fā)布兩次消息
(integer) 1
127.0.0.1:6379> PUBLISH redisChat "hello redis"
(integer) 1

Transactions

MULTI 须鼎、 EXEC 鲸伴、 DISCARD 和 WATCH 是 Redis 事務(wù)相關(guān)的命令府蔗。事務(wù)可以一次執(zhí)行多個(gè)命令, 并且?guī)в幸韵聝蓚€(gè)重要的保證:

  • 事務(wù)是一個(gè)單獨(dú)的隔離操作:事務(wù)中的所有命令都會(huì)序列化汞窗、按順序地執(zhí)行姓赤。事務(wù)在執(zhí)行的過(guò)程中,不會(huì)被其他客戶端發(fā)送來(lái)的命令請(qǐng)求所打斷杉辙。
  • 事務(wù)是一個(gè)原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行捶朵。

Redis還提供了一個(gè)Watch功能蜘矢,你可以對(duì)一個(gè)key進(jìn)行Watch,然后再執(zhí)行Transactions综看,在這過(guò)程中品腹,如果這個(gè)Watched的值進(jìn)行了修改,那么這個(gè)Transactions會(huì)發(fā)現(xiàn)并拒絕執(zhí)行红碑。 參考地址鏈接

127.0.0.1:6379> MULTI #開(kāi)啟了一個(gè)事務(wù)
OK
127.0.0.1:6379> SET book-name "Mastering C++ in 21 days" #將命令放入隊(duì)列中
QUEUED
127.0.0.1:6379> GET book-name
QUEUED
127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED
127.0.0.1:6379> SMEMBERS tag
QUEUED
127.0.0.1:6379> EXEC #開(kāi)啟事務(wù)之后執(zhí)行
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "C++"
   2) "Mastering Series"
   3) "Programming"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> set b 2
QUEUED
127.0.0.1:6379> DISCARD #清空事務(wù)隊(duì)列,并放棄執(zhí)行事
OK

WATCH 命令可以為 Redis 事務(wù)提供 check-and-set (CAS)行為(實(shí)現(xiàn)樂(lè)觀鎖):

客戶端1:

127.0.0.1:6379> set count 1
OK
127.0.0.1:6379> WATCH count #監(jiān)視一個(gè)key
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a aa
QUEUED
127.0.0.1:6379> set b bb
QUEUED
127.0.0.1:6379> EXEC #在另一個(gè)客戶端修改了監(jiān)視的key后舞吭,執(zhí)行事務(wù)命令
(nil)
127.0.0.1:6379> keys *
1) "count"

客戶端2

127.0.0.1:6379> INCR count
(integer) 2
127.0.0.1:6379> get count
"2"

redis配置主從

  • 復(fù)制兩臺(tái)redis實(shí)例(6379,6380)
  • 實(shí)例6379(master) redis.conf配置信息如下:
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
  • 實(shí)例6380(slave) redis.conf配置信息如下:
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
slaveof 127.0.0.1 6379 #指向master的地址端口
  • 測(cè)試
127.0.0.1:6379> set name admin
OK
127.0.0.1:6380> get name
"admin"

redis 哨兵模式

Redis Sentinel 是一個(gè)分布式系統(tǒng)析珊, 你可以在一個(gè)架構(gòu)中運(yùn)行多個(gè) Sentinel 進(jìn)程(progress)羡鸥, 這些進(jìn)程使用流言協(xié)議(gossip protocols)來(lái)接收關(guān)于主服務(wù)器是否下線的信息, 并使用投票協(xié)議(agreement protocols)來(lái)決定是否執(zhí)行自動(dòng)故障遷移忠寻, 以及選擇哪個(gè)從服務(wù)器作為新的主服務(wù)器惧浴。 參考文檔鏈接地址

  1. 配置redis主從復(fù)制
  • 創(chuàng)建實(shí)例目錄


    Selection_001.png
  • 復(fù)制執(zhí)行腳本


    Selection_002.png
  • 創(chuàng)建一個(gè)新的redis實(shí)例


    Selection_003.png
  • 主要修改redis.conf文件內(nèi)容如下(master配置):

bind 127.0.0.1
port 7000
daemonize yes #啟動(dòng)redis后臺(tái)運(yùn)行
masterauth admin # master的密碼,如果redis設(shè)置了密碼奕剃,主從密碼要設(shè)置成一樣的
requirepass admin
data /home/xiaodongsun/Documents/redis-sentinel/7000/data
pidfile /var/run/redis_7000.pid
logfile /home/xiaodongsun/Documents/redis-sentinel/7000/data/redis_7000.log
  • 復(fù)制實(shí)例到7001,7002


    Selection_004.png
  • 修改實(shí)例7001和7002 redis.conf文件內(nèi)容如下(slave配置):
vim ./7001/redis.conf #編輯配置文件
:%s/7000/7001/g #全局替換原實(shí)例配置
slaveof 127.0.0.1 7000 #指定master地址以及端口
  • 啟動(dòng)redis服務(wù):


    Selection_004.png
  • 測(cè)試主從復(fù)制


    Selection_005.png
  1. 搭建Sentinel系統(tǒng)
  • 修改7000 Sentinel實(shí)例的配置文件 sentinel.conf 衷旅,配置如下:
bind 127.0.0.1
port 26379
daemonize yes
dir /home/xiaodongsun/Documents/redis-sentinel/7000/data
logfile /home/xiaodongsun/Documents/redis-sentinel/7000/data/redis-sentinel.log
sentinel auth-pass mymaster admin
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
  • 修改7001 Sentinel實(shí)例的配置文件 sentinel.conf ,配置如下:
bind 127.0.0.1
port 26380
daemonize yes
dir /home/xiaodongsun/Documents/redis-sentinel/7001/data
logfile /home/xiaodongsun/Documents/redis-sentinel/7001/data/redis-sentinel.log
sentinel auth-pass mymaster admin
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
  • 修改7002 Sentinel實(shí)例的配置文件 sentinel.conf 纵朋,配置如下:
bind 127.0.0.1
port 26381
daemonize yes
dir /home/xiaodongsun/Documents/redis-sentinel/7002/data
logfile /home/xiaodongsun/Documents/redis-sentinel/7002/data/redis-sentinel.log
sentinel auth-pass mymaster admin
sentinel monitor mymaster 127.0.0.1 7000 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
  • 啟動(dòng)各臺(tái)哨兵實(shí)例


    Selection_007.png

至此redis哨兵已初步搭建完成

  1. 測(cè)試
  • 查看redis主從信息


    master相關(guān)信息
slave相關(guān)信息
  • 故障轉(zhuǎn)移(在master上做下線操作在其他slave上查看新的信息)


    Selection_010.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柿顶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子操软,更是在濱河造成了極大的恐慌嘁锯,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聂薪,死亡現(xiàn)場(chǎng)離奇詭異猪钮,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)胆建,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)烤低,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人笆载,你說(shuō)我怎么就攤上這事扑馁⊙纳耄” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵腻要,是天一觀的道長(zhǎng)复罐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)雄家,這世上最難降的妖魔是什么效诅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮趟济,結(jié)果婚禮上乱投,老公的妹妹穿的比我還像新娘。我一直安慰自己顷编,他們只是感情好戚炫,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著媳纬,像睡著了一般双肤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钮惠,一...
    開(kāi)封第一講書(shū)人閱讀 52,584評(píng)論 1 312
  • 那天茅糜,我揣著相機(jī)與錄音,去河邊找鬼素挽。 笑死限匣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的毁菱。 我是一名探鬼主播米死,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼贮庞!你這毒婦竟也來(lái)了峦筒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤窗慎,失蹤者是張志新(化名)和其女友劉穎物喷,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體遮斥,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡峦失,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了术吗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尉辑。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖较屿,靈堂內(nèi)的尸體忽然破棺而出隧魄,到底是詐尸還是另有隱情卓练,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布购啄,位于F島的核電站襟企,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏狮含。R本人自食惡果不足惜顽悼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望几迄。 院中可真熱鬧蔚龙,春花似錦、人聲如沸乓旗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)屿愚。三九已至,卻和暖如春务荆,著一層夾襖步出監(jiān)牢的瞬間妆距,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工函匕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娱据,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓盅惜,卻偏偏與公主長(zhǎng)得像中剩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抒寂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361