redis 基础总结

redis简介:

官方链接:跳转地址;中文官方链接:跳转地址

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

可以对这些类型运行原子操作,例如附加到字符串;递增哈希值;将元素推送到列表中;计算集合交集,并集和差异;或者在排序集中获得排名最高的成员。

为了实现其出色的性能,Redis使用内存数据集。根据您的使用情况,您可以通过每隔一段时间将数据集转储到磁盘或通过将每个命令附加到日志来保留它。如果您只需要功能丰富的网络内存缓存,则可以选择禁用持久性。

Redis还支持简单到设置的主从异步复制,具有非常快速的非阻塞第一次同步,自动重新连接以及在网络分割上的部分重新同步。

其他功能包括:

  • 事物
  • 发布/订阅
  • Lua脚本
  • 设置key的生存时间
  • LRU驱逐key(更新缓存)
  • 自动故障转移

Redis是用ANSI C编写的,适用于大多数POSIX系统,如Linux,* BSD,OS X,没有外部依赖性。Linux和OS X是Redis开发和测试的两个操作系统,我们建议使用Linux进行部署。Windows版本没有官方支持,但Microsoft开发并维护了Redis的Win-64端口。

redis单机版使用

下载链接:跳转地址

下载以及安装

1.安装单机版参考redis官网

$ 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.启动默认安装好的redis服务

$ src/redis-server

3.查看redis默认配置信息:

$ src/redis-cli info

添加认证以及后台启动模式

修改redis配置redis.conf文件,修改以下内容即可

daemonize yes
requirepass YouPassword

重启redis服务并指定配置文件,即生效

$ 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常用数据类型

redis最为常用的数据类型主要有以下:

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

String

Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字.
常用命令: 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对应的值重新赋值,并返回key对应的原有值
"1"
127.0.0.1:6379> MGET test count string #MEGT/MSET一次性获取或存储多个key对应的值
1) "getset"
2) "1"
3) "admin"

应用场景:String是最常用的一种数据类型,普通的key/ value 存储都可以归为此类.即可以完全实现目前 Memcached 的功能,并且效率更高。还可以享受Redis的定时持久化,操作日志及 Replication等功能。除了提供与 Memcached 一样的get、set、incr、decr 等操作外,Redis还提供了下面一些操作:

  • 获取字符串长度
  • 往字符串append内容
  • 设置和获取字符串的某一段内容
  • 设置及获取字符串的某一位(bit)
  • 批量设置一系列字符串的内容

实现方式:

String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。

修改或查询键空间

有些指令不是针对任何具体的类型定义的,而是用于和整个键空间交互的。因此,它们可被用于任何类型的键。

使用EXISTS命令返回1或0标识给定key的值是否存在,使用DEL命令可以删除key对应的值,DEL命令返回1或0标识值是被删除(值存在)或者没被删除(key对应的值不存在)。

127.0.0.1:6379> EXISTS count #判断是否存在该key
(integer) 1
127.0.0.1:6379> DEL count #删除键值对
(integer) 1
127.0.0.1:6379> TYPE string #key对应的值的存储类型
string

redis超时:数据在限定时间内存活

127.0.0.1:6379> EXPIRE string 20 #为已经存在的key设置存活时间
(integer) 1
127.0.0.1:6379> TTL string #TTL命令用来查看key对应的值剩余存活时间。
(integer) 14
127.0.0.1:6379> SET expire 10ms ex 60 #设置键值对的时候,指定存活时间
OK
127.0.0.1:6379> TTL expire
(integer) 53

Lists

Redis lists基于Linked Lists实现。这意味着即使在一个list中有数百万个元素,在头部或尾部添加一个元素的操作,其时间复杂度也是常数级别的。用LPUSH 命令在十个元素的list头部添加新元素,和在千万元素list头部添加新元素的速度相同。

那么,坏消息是什么?在数组实现的list中利用索引访问元素的速度极快,而同样的操作在linked list实现的list上没有那么快。
Redis Lists用linked list实现的原因是:对于数据库系统来说,至关重要的特性是:能非常快的在很大的列表上添加元素。另一个重要因素是,正如你将要看到的:Redis lists能在常数时间取得常数长度。

如果快速访问集合元素很重要,建议使用可排序集合(sorted sets)。可排序集合我们会随后介绍。

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

127.0.0.1:6379> LSET lists 0 a #当key不存在报错
(error) ERR no such key
127.0.0.1:6379> RPUSH lists a #向list左边添加一个新元素,若key不存在则新建一个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 带有两个索引,一定范围的第一个和最后一个元素。这两个索引都可以为负来告知Redis从尾部开始计数,因此-1表示最后一个元素,-2表示list中的倒数第二个元素,以此类推。
1) "A"
2) "a"
27.0.0.1:6379> RPUSH lists b c d e f #一次向list存入多个值
(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中删除元素并同时返回删除的值。可以在左边或右边操作。(抽奖)
"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 #在这最后 列表中的命令序列是空的,没有更多的元素可以被弹出。
(nil)
127.0.0.1:6379> LTRIM list 0 2 #可以使用LTRIM把list从左边截取指定长度
OK
127.0.0.1:6379> LRANGE list 0 -1
1) "b"
2) "c"
3) "d"
127.0.0.1:6379> LLEN list #list长度
(integer) 3

应用场景:
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。

Lists 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。Lists的另一个应用就是消息队列,
可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api,你可以直接查询,删除Lists中某一段的元素。

实现方式:

Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

Hash

Redis hash 看起来就像一个 “hash” 的样子,由键值对组成,Hash 便于表示 objects,实际上,你可以放入一个 hash 的域数量实际上没有限制(除了可用内存以外)。所以,你可以在你的应用中以不同的方式使用 hash。值得注意的是,小的 hash 被用特殊方式编码,非常节约内存。hash指令的完整列表,常用命令:hget,hset,hgetall 等。

127.0.0.1:6379> HMSET user:01 username admin birthyear 1995 verified 1 #设置 hash 中的多个域
OK
127.0.0.1:6379> HGET user:01 username #取回单个域
"admin"
127.0.0.1:6379> HGET user:01 birthyear
"1995"
127.0.0.1:6379> HMGET user:01 username verified #取回指定的多个域,类似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 #字符长度
(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中存储的哈希中包含的字段数
(integer) 4
127.0.0.1:6379> HINCRBY user:01 birthyear -1 #执行递增和递减操作
(integer) 1994
127.0.0.1:6379> HINCRBYFLOAT user:01 birthyear 0.5 #执行浮点递增和递减操作
"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"

应用场景:在Memcached中,我们经常将一些结构化的信息打包成HashMap,在客户端序列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。

简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息:

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:

第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。

第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。

那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。也就是说,Key仍然是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。

这里同时需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意。

实现方式:

Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

Set

Redis Set 是 String 的无序排列。SADD 指令把新的元素添加到 set 中。对 set 也可做一些其他的操作,比如测试一个给定的元素是否存在,对不同 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成员,去重并且无序排列
1) "1"
2) "b"
3) "a"
127.0.0.1:6379> SISMEMBER array a #检测特定的元素是否存在
(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 #对多个集合取并集,并把结果存入另一个 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 #随机从set集合中获取一个值(发牌)
"S5"
127.0.0.1:6379> SPOP game:1:deck
"H9"
127.0.0.1:6379> SCARD game:1:deck #set里剩余元素数量
(integer) 50
127.0.0.1:6379> SRANDMEMBER game:1:deck #获取随机元素而不从集合中删除它
"D5"

应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

Sets 集合的概念就是一堆不重复值的组合。利用Redis提供的Sets数据结构,可以存储一些集合性的数据,比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。

实现方式:

set 的内部实现是一个value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

Sorted Set

Sorted sets是一种数据类型,类似于Set和Hash之间的混合。与集合一样,有序集合由唯一的,非重复的字符串元素组成,因此在某种意义上,有序集合也是一个集合。

排序集合中的元素按顺序排列(因此它们不是根据请求排序的,顺序是用于表示排序集合的数据结构的特性)。它们按照以下规则订购:

  • 如果A和B是两个具有不同分数的元素,那么A> B,如果A.score是> B.score。
  • 如果A和B具有完全相同的score,那么如果A字符串在字典上大于B字符串,则A> B.A和B字符串不能相等,因为有序集只有唯一元素。
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 #通过索引区间返回有序集合成指定区间内的成员;返回按出生年份排序的黑客列表,0和-1表示从元素索引0到最后一个元素
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 #通过索引区间返回有序集合成指定区间内的成员以及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年间出生的所有黑客,并返回已删除元素的数量。
(integer) 3
127.0.0.1:6379> ZRANK hackers "Alan Kay" #询问有序元素集中元素的位置
(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" #插入了相同的相同分数,按字典顺序获取,
(integer) 9
127.0.0.1:6379> ZRANGE hackers 0 -1 #由于排序集排序规则,它们已经按字典顺序排序:
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"

使用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。

另外还可以用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

实现方式:

Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

Pub/Sub

Pub/Sub 从字面上理解就是发布(Publish)与订阅(Subscribe),在Redis中,你可以设定对某一个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,所有订阅它的客户端都会收到相应的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即时聊天,群聊等功能。

客户端1:

127.0.0.1:6379> SUBSCRIBE redisChat #创建了订阅频道名为 redisChat,订阅者就能接收到消息。
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
# 订阅者的客户端会显示如下消息
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" #在同一个频道 redisChat 发布两次消息
(integer) 1
127.0.0.1:6379> PUBLISH redisChat "hello redis"
(integer) 1

Transactions

MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

Redis还提供了一个Watch功能,你可以对一个key进行Watch,然后再执行Transactions,在这过程中,如果这个Watched的值进行了修改,那么这个Transactions会发现并拒绝执行。 参考地址链接

127.0.0.1:6379> MULTI #开启了一个事务
OK
127.0.0.1:6379> SET book-name "Mastering C++ in 21 days" #将命令放入队列中
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 #开启事务之后执行
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 #清空事务队列,并放弃执行事
OK

WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为(实现乐观锁):

客户端1:

127.0.0.1:6379> set count 1
OK
127.0.0.1:6379> WATCH count #监视一个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 #在另一个客户端修改了监视的key后,执行事务命令
(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配置主从

  • 复制两台redis实例(6379,6380)
  • 实例6379(master) redis.conf配置信息如下:
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
  • 实例6380(slave) redis.conf配置信息如下:
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
slaveof 127.0.0.1 6379 #指向master的地址端口
  • 测试
127.0.0.1:6379> set name admin
OK
127.0.0.1:6380> get name
"admin"

redis 哨兵模式

Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。 参考文档链接地址

  1. 配置redis主从复制
  • 创建实例目录


    Selection_001.png
  • 复制执行脚本


    Selection_002.png
  • 创建一个新的redis实例


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

bind 127.0.0.1
port 7000
daemonize yes #启动redis后台运行
masterauth admin # master的密码,如果redis设置了密码,主从密码要设置成一样的
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
  • 复制实例到7001,7002


    Selection_004.png
  • 修改实例7001和7002 redis.conf文件内容如下(slave配置):
vim ./7001/redis.conf #编辑配置文件
:%s/7000/7001/g #全局替换原实例配置
slaveof 127.0.0.1 7000 #指定master地址以及端口
  • 启动redis服务:


    Selection_004.png
  • 测试主从复制


    Selection_005.png
  1. 搭建Sentinel系统
  • 修改7000 Sentinel实例的配置文件 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实例的配置文件 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实例的配置文件 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
  • 启动各台哨兵实例


    Selection_007.png

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

  1. 测试
  • 查看redis主从信息


    master相关信息
slave相关信息
  • 故障转移(在master上做下线操作在其他slave上查看新的信息)


    Selection_010.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345