Redis的优势
-
性能极高
-
数据类型丰富,单键值对最大支持512M大小的数据
-
简单易用,支持所有主流编程语言
-
支持数据持久化,主从复制,哨兵模式等高可用特性
Redis数据类型
Redis基本数据类型
字符串 String
设置键name,键是区分大小写的
127.0.0.1:6379> set name cxz
OK
127.0.0.1:6379> get name
"cxz"
127.0.0.1:6379> set Name cxzzz
OK
127.0.0.1:6379> get Name
"cxzzz"
判断键是否存在,存在的话,返回1 ,不存在的话,返回0
127.0.0.1:6379> exists Name
(integer) 1
删除相应的键
127.0.0.1:6379> del Name
(integer) 1
127.0.0.1:6379> exists Name
(integer) 0
127.0.0.1:6379> exists name
(integer) 1
查询所有的键
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> set age 12
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
查询以me结尾的键
127.0.0.1:6379> keys *me
1) "name"
删除数据库中所有的键 (慎用)
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty array)
Redis中的键和值都是以二进制的形式存储的,不支持中文
127.0.0.1:6379> set name 一键三链
OK
127.0.0.1:6379> get name
将中文换成的二进制的形式,这里的x表示后面的内容是十六进制的
"\xe4\xb8\x80\xe9\x94\xae\xe4\xb8\x89\xe9\x93\xbe"
要想看到中文
127.0.0.1:6379> quit
--row参数 表示以原始的数据来显示内容
[root@localhost conf]# docker exec -it redis redis-cli --raw
127.0.0.1:6379> keys *
name
127.0.0.1:6379> get name
一键三链
如何设置一个带有过期时间的键值对
127.0.0.1:6379> TTL name
返回-1表示没有设置过期时间
-1
现在设置一下过期时间
127.0.0.1:6379> expire name 10
1
127.0.0.1:6379> ttl name
6
127.0.0.1:6379> ttl name
0
返回-2表示已过期
127.0.0.1:6379> ttl name
-2
127.0.0.1:6379> ttl name
-2
过期后,通过get 键 就得不到值了,keys 命令也看不到这个键
127.0.0.1:6379> get name
127.0.0.1:6379> keys name
127.0.0.1:6379>
还可以通过setex 键 过期时间 值 来设置键的过期时间
127.0.0.1:6379> setex name 10 一键三联
OK
127.0.0.1:6379> ttl name
5
127.0.0.1:6379> ttl name
1
127.0.0.1:6379> ttl name
-2
127.0.0.1:6379> ttl name
-2
127.0.0.1:6379>
setnx 只有当键不存在的时候才设置键的值,如果键已存在,那么setnx命令不做任何动作
127.0.0.1:6379> setnx name vc
1
127.0.0.1:6379> setnx name vcr
0
127.0.0.1:6379> get name
vc
列表 List
127.0.0.1:6379> lpush letter a
1
-- lrange 键 起始位置 结束位置
-- -1是最后一个元素 0 -1 是遍历列表中的所有元素
127.0.0.1:6379> lrange letter 0 -1
a
-- 返回的是列表中元素的个数
127.0.0.1:6379> lpush letter b
2
127.0.0.1:6379> lrange letter 0 -1
b
a
-- lpush 可以一次添加多个元素
127.0.0.1:6379> lpush letter c d e
5
-- lrange 是从左到右依次将列表中的元素输出
127.0.0.1:6379> lrange letter 0 -1
e
d
c
b
a
127.0.0.1:6379>
-- 从右边往列表中添加元素,返回列表中元素的值
127.0.0.1:6379> rpush letter f
6
127.0.0.1:6379> lrange letter 0 -1
e
d
c
b
a
f
-- rpop 键 个数 从列表的右边删除几个元素,返回删除元素的值
127.0.0.1:6379> rpop letter
f
127.0.0.1:6379> lrange letter 0 -1
e
d
c
b
a
127.0.0.1:6379>
-- lpop从左删
127.0.0.1:6379> lpop letter 2
e
d
127.0.0.1:6379> lrange letter 0 -1
c
b
a
-- 返回列表的长度
127.0.0.1:6379> llen letter
3
-- 删除所有的键
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> lrange letter 0 -1
127.0.0.1:6379> lpush letter a b c d e
5
127.0.0.1:6379> lrange letter 0 -1
e
d
c
b
a
-- 删除1到3 以外的元素
127.0.0.1:6379> ltrim letter 1 3
OK
127.0.0.1:6379> lrange letter 0 -1
d
c
b
127.0.0.1:6379>
集合 Set
-- 列表list中的元素是可以重复的,而set中的元素是不能重复的
-- sadd 键 值一个或者多个
127.0.0.1:6379> sadd course Redis
1
-- 查询这个键种所有的值
127.0.0.1:6379> smembers course
Redis
-- set中的元素不能重复
127.0.0.1:6379> sadd course Redis
0
127.0.0.1:6379> smembers course
Redis
-- sismember 键 值 判断这个值是否存在,存在为1,不存在为0
127.0.0.1:6379> sismember course Redis
1
127.0.0.1:6379> sismember course Python
0
-- 删除集合中相应的值
127.0.0.1:6379> srem course Redis
1
127.0.0.1:6379> sismember course Redis
0
有序集合 SortedSet(ZSet)
它和集合的区别是有序集合中的每个元素都会关联一个浮点类型的分数,然后按照这个分数,来对集合中的元素进行从小到大的排序,有序集合的成员是唯一的,但是分数是可以重复的
127.0.0.1:6379>
127.0.0.1:6379> zadd res 680 清华 660 北大 650 复旦
3
127.0.0.1:6379> zadd res 640 浙大
1
127.0.0.1:6379>
127.0.0.1:6379> zrange res 0 -1
浙大
复旦
北大
清华
-- 加上withscores查询值的时候带上相应的分数
127.0.0.1:6379> zrange res 0 -1 withscores
浙大
640
复旦
650
北大
660
清华
680
127.0.0.1:6379>
-- 查看某个值的分数
127.0.0.1:6379> zscore res 清华
680
-- 查看值的排名, 返回的是index ,因为不是从小到大排序的
127.0.0.1:6379> zrank res 清华
3
127.0.0.1:6379>
-- 查看值的排名,从大到小
127.0.0.1:6379> zrevrank res 清华
0
127.0.0.1:6379>
-- 删除相应的值
127.0.0.1:6379> zrem res 清华
1
127.0.0.1:6379> zrange res 0 -1
浙大
复旦
北大
127.0.0.1:6379>
哈希 Hash
127.0.0.1:6379> hset person name cxz
1
127.0.0.1:6379> hset person age 21
1
127.0.0.1:6379> hget person name
cxz
127.0.0.1:6379> hget person age
21
127.0.0.1:6379> hgetall person
name
cxz
age
21
-- 删除person中的age键
127.0.0.1:6379> hdel person age
1
127.0.0.1:6379>
-- 获取所有键值对
127.0.0.1:6379> hgetall person
name
cxz
-- 判断person中键name是否存在
127.0.0.1:6379> hexists person name
1
127.0.0.1:6379> hexists person age
0
127.0.0.1:6379>
-- 获取所有的键
127.0.0.1:6379> hkeys person
name
-- 获取键的个数
127.0.0.1:6379> hlen person
1
Redis 高级数据类型
消息队列 Stream
-- stream是一个轻量级的消息队列,可以解决发布订阅的局限性,比如消息无法持久化,无法记录历史消息等等。
-- stream中相关的命令都以x开头
-- * 皓表示自动生成一个消息的ID
127.0.0.1:6379> xadd cxz * course redis
-- 这个回显信息就是消息的ID
1740297567474-0
127.0.0.1:6379> xadd cxz * course java
1740298307156-0
127.0.0.1:6379> xadd cxz * course go
1740298328148-0
127.0.0.1:6379>
-- 查询消息的数量
127.0.0.1:6379> xlen cxz
3
-- 查询所有的消息,开始用'-',结束用'+'
127.0.0.1:6379> xrange cxz - +
1740297567474-0
course
redis
1740298307156-0
course
java
1740298328148-0
course
go
-- 删除消息
127.0.0.1:6379> xdel cxz 1740298307156-0
1
127.0.0.1:6379> xrange cxz - +
1740297567474-0
course
redis
1740298328148-0
course
go
-- 删除消息还可以用xtrim, 其中maxlen 0代表删除所有消息
127.0.0.1:6379> xtrim cxz maxlen 0
2
127.0.0.1:6379> xrange cxz - +
127.0.0.1:6379>
-- 手动生成消息的ID
127.0.0.1:6379> xadd cxz 1-0 course docker
1-0
-- XADD:这是 Redis Streams 数据结构的命令,用于向流(Stream)中添加一条新消息。
-- cxz:这是流的名称。流是 Redis 的一种数据结构,类似于一种消息队列,用于存储按顺序排列的消息。
-- 1-0:这是消息的 ID。Redis 流中的每个消息都有一个唯一的 ID,通常由两部分组成:timestamp-ms-sequence。例如,1-0 表示时间戳为 1(以毫秒为单位),序列号为 0。
-- course docker:这是添加到流中的消息内容。其中 course 是字段名称,docker 是字段值。你可以添加多个字段,每个字段以空格分隔。
127.0.0.1:6379> xread count 2 block 1000 streams cxz 0
1) 1) "cxz"
2) 1) 1) "1-0"
2) 1) "course"
2) "docker"
2) 1) "2-0"
2) 1) "course"
2) "git"
-- XREAD:这是 Redis 的命令,用于从一个或多个流中读取数据。
-- COUNT 2:可选参数,表示每次读取最多返回的消息数量。这里指定最多返回 2 条消息。
-- BLOCK 1000:可选参数,表示如果流中没有新消息,命令将阻塞最多 1000 毫秒(1 秒),等待新消息到达。
-- STREAMS cxz 0:
-- STREAMS:指定要读取的流。
-- cxz:流的名称。
-- 0:表示从流中 ID 大于 0 的第一条消息开始读取。如果流中没有消息,或者所有消息的 ID 都小于或等于 0,则会根据 BLOCK 参数决定是否阻塞
127.0.0.1:6379> xread count 2 block 1000 streams cxz 1
1) 1) "cxz"
2) 1) 1) "2-0"
2) 1) "course"
2) "git"
2) 1) "3-0"
2) 1) "course"
2) "redis"
-- 如果5大于消息队列中的最大的ID,那么就会阻塞,这里设置的阻塞时间是1秒,然后返回nil
127.0.0.1:6379> xread count 2 block 1000 streams cxz 5
(nil)
(1.08s)
-- 1.先执行这个
-- $ 表示从流的最新消息开始读取。换句话说,它会跳过之前已经存在的所有消息,只读取在命令执行后新产生的消息。
127.0.0.1:6379> xread count 2 block 10000 streams cxz $
1) 1) "cxz"
2) 1) 1) "4-0"
2) 1) "course"
2) "nginx"
(2.55s)
-- 2.再执行这个
127.0.0.1:6379> xadd cxz 4-0 course nginx
"4-0"
-- 创建消费者组
-- group1是消费者的名称
-- 0 这是消费者组的起始位置,它指定了消费者从流的哪个位置开始读取消息,0的含义是从流的最早消息开始读取,其他常见值包括:
-- $:从流的最新消息开始读取(忽略之前的消息)
-- <ID>: 从指定的消息ID开始读取
-- 执行这条命令后,Redis 会在名为 cxz 的流上创建一个名为 group1 的消费者组,并且该组从流的最早消息(ID 为 0)开始读取。
127.0.0.1:6379> xgroup create cxz group1 0
OK
-- 获取消费者组信息
127.0.0.1:6379> xinfo groups cxz
1) 1) "name" -- 消费者组的名称
2) "group1"
3) "consumers" -- 消费者组中消费者数量
4) (integer) 0
5) "pending" -- 消费者组中尚未被确认的消息数量
6) (integer) 0
7) "last-delivered-id" -- 消费者组中最后一次成功从流中读取的消息的ID
8) "0-0"
9) "entries-read" -- 消费者组已经读取的消息总数
10) (nil)
11) "lag" -- 流中未被消费者组处理的消息的数量
12) (integer) 4
127.0.0.1:6379>
-- 添加消费者
-- 将下面三个消费者添加到group1中
127.0.0.1:6379> xgroup createconsumer cxz group1 consumer1
(integer) 1
127.0.0.1:6379> xgroup createconsumer cxz group1 consumer2
(integer) 1
127.0.0.1:6379> xgroup createconsumer cxz group1 consumer3
(integer) 1
-- 再次查看消费者的信息,可以看到,消费者组中多了3个消费者
127.0.0.1:6379> xinfo groups cxz
1) 1) "name"
2) "group1"
3) "consumers"
4) (integer) 3
5) "pending"
6) (integer) 0
7) "last-delivered-id"
8) "0-0"
9) "entries-read"
10) (nil)
11) "lag"
12) (integer) 4
-- xreadgroup:用于从流中读取消息,它允许消费者从流中读取消息,并支持消费者机制。
-- group1消费者组的名字,consumer1消费者的名称
-- count 2:表示最多读取2条消息
-- block 3000: 如果流中暂时没有新消息,命令会阻塞3秒,如果这段时间内有新消息到达,命令会立即返回
-- cxz是流的名称
-- > 是消费者组的特殊值,表示从消费者组的“游标”位置开始读取新消息
-- last-delivered-id 是消费者组的游标位置,表示消费者组最后一次成功读取的消息 ID。它是一个特殊的 ID,用于标记消费者组的读取进度。
127.0.0.1:6379> xreadgroup group group1 consumer1 count 2 block 3000 streams cxz >
1) 1) "cxz"
2) 1) 1) "1-0"
2) 1) "course"
2) "docker"
2) 1) "2-0"
2) 1) "course"
2) "git"
消息队列stream 中,流(stream),消费者(Consumer)和消费者组(Consumer Group)之间的关系
在 Redis Streams 中,流(Stream)、消费者(Consumer)和消费者组(Consumer Group)是紧密相关的概念,它们共同构成了 Redis Streams 的消息处理机制。以下是对它们之间关系的详细解释:
- 流(Stream)
流是 Redis Streams 的核心数据结构,它是一个持久化的、追加式的日志结构,用于存储有序的消息(message)。每个消息都有一个唯一的 ID,按照插入顺序递增。
-
特点:
- 流是消息的集合,消息以追加的方式插入。
- 每条消息都有一个唯一的 ID,格式为
<timestamp-milliseconds>-<sequence>,例如1693072800-0。 - 流支持多个消费者和消费者组,可以灵活地读取消息。
-
用途:
- 流用于存储和传递消息,是消息的“容器”。
- 消费者(Consumer)
消费者是读取流中消息的客户端。它可以是一个应用程序、一个线程或一个服务实例,负责从流中读取消息并处理它们。
-
特点:
- 消费者可以独立地从流中读取消息。
- 消费者可以属于一个消费者组,也可以独立工作。
-
作用:
- 消费者负责处理流中的消息,例如执行任务、记录日志或触发事件。
- 消费者组(Consumer Group)
消费者组是一个逻辑上的消费者集合,用于将多个消费者组织在一起,共同消费一个流中的消息。消费者组的主要作用是实现负载均衡和消息分发。
-
特点:
- 消费者组将流中的消息分配给组内的消费者,避免消息被重复消费。
- 每个消费者组维护一个游标(cursor),记录当前消费的位置。
- 消费者组支持消息确认机制(acknowledgment),只有消费者显式确认后,消息才被视为已处理。
-
作用:
- 消费者组允许多个消费者协同工作,提高消息处理的效率和可靠性。
- 消费者组可以实现负载均衡,将消息均匀分配给组内的消费者。
三者之间的关系
流(Stream)
流是消息的存储结构,是消费者和消费者组的“数据源”。消费者和消费者组通过流来读取消息。
消费者(Consumer)
消费者是消息的处理者,可以独立地从流中读取消息,也可以属于一个消费者组。消费者的主要任务是从流中读取消息并处理它们。
消费者组(Consumer Group)
消费者组是多个消费者的集合,用于管理消费者对流的消费行为。消费者组的主要作用是:
- 负载均衡:将流中的消息分配给组内的消费者,避免消息被重复消费。
- 消息确认机制:只有消费者显式确认后,消息才被视为已处理。
- 故障转移:如果某个消费者失败,其他消费者可以接管未处理的消息。
示例场景
假设你有一个 Redis Stream 名为 logs,用于存储日志消息。你希望多个服务实例(消费者)共同处理这些日志消息。你可以这样操作:
-
创建流:
XADD logs * log "This is a log message" -
创建消费者组:
XGROUP CREATE logs group1 0- 流名:
logs - 消费者组名:
group1 - 从最早的消息开始读取:
0
- 流名:
-
消费者加入消费者组:
-
消费者1:
XREADGROUP GROUP group1 consumer1 STREAMS logs > -
消费者2:
XREADGROUP GROUP group1 consumer2 STREAMS logs >
-
-
消息分配:
-
Redis 会自动将消息分配给组内的消费者,避免重复消费。
-
消费者处理消息后需要确认:
XACK logs group1 <message-id>
-
总结
- 流(Stream):消息的存储结构,是消费者和消费者组的数据源。
- 消费者(Consumer):消息的处理者,可以独立工作或属于消费者组。
- 消费者组(Consumer Group):管理消费者对流的消费行为,实现负载均衡和消息确认机制。
通过合理使用流、消费者和消费者组,Redis Streams 可以高效地实现消息队列、日志处理、分布式任务分发等功能。
地理空间 Geospatial
-- 添加位置信息,可以添加一个或者多个
127.0.0.1:6379> Geoadd city 116.39 39.91 beijing 121.47 31.23 shanghai 113.23 23.16 guangzhou 104.07 30.57 chengdu
(integer) 4
-- 获取某个地理位置的经纬度,返回结果是一个数组,第一个表示经度,第二个表示纬度
127.0.0.1:6379> Geopos city beijing
1) 1) "116.38999968767166138"
2) "39.90999956664450821"
-- 获取两个位置的距离,默认单位是米
127.0.0.1:6379> geodist city beijing shanghai
"1068756.9106"
-- 加个km 返回的是公里
127.0.0.1:6379> geodist city beijing shanghai km
"1068.7569"
-- 搜索指定范围内的成员并返回,可以以成员的位置或者一个指定的经纬度为中心,按照圆形或者矩形的范围搜索
-- 按照圆形进行搜索
127.0.0.1:6379> geosearch city frommember shanghai byradius 2000 km
1) "chengdu"
2) "guangzhou"
3) "shanghai"
4) "beijing"
-- 按照矩形进行搜索
-- 1000为宽 2000为高
127.0.0.1:6379> GEOSEARCH city FROMMEMBER shanghai BYBOX 1000 2000 KM
1) "shanghai"
2) "beijing"
HyperLogLog
-- HyperLogLog是一种用来做基数统计的算法
-- 先说一下什么是基数? 如果一个集合中所有的元素都是不相同的,那么这个集合的基数就是集合中元素的个数
-- HyperLogLog的原理
-- 它的原理是使用随机算法来计算,通过牺牲一定的精确度,来换取更小的内存消耗,
-- 优点:占用内存小
-- 缺点:会有一定的误差
-- 适合用来做一些对精确度要求不高,而且数据量非常大的统计工作,比如统计某个网站的UV (UV是指在一定的时间内访问网站的独立访客数量,具体来说,UV表示在24小时内网站的不同用户数量,同一个用户在一天内多次访问网站只计算一个UV),统计某个词的搜索次数等等。
-- 命令以PF开头
-- 将一个或者多个元素添加到HyperLogLog数据结构中
127.0.0.1:6379> pfadd course git docker redis
(integer) 1
-- 返回HyperLogLog中估算的唯一元素数量
127.0.0.1:6379> pfcount course
(integer) 3
127.0.0.1:6379> pfadd course nginx
(integer) 1
127.0.0.1:6379> pfcount course
(integer) 4
127.0.0.1:6379> pfadd course2 python git go
(integer) 1
-- pfmerge 用于将多个HyperLogLog合并为一个HyperLogLog,合并后的 HyperLogLog 的基数估算值是通过对所有给定 HyperLogLog 进行并集计算得出的。
127.0.0.1:6379> pfmerge result course course2
OK
127.0.0.1:6379> pfcount result
(integer) 6
127.0.0.1:6379>
位图 Bitmap
-- 位图是字符串类型的扩展,可以使用一个string类型来定义一个数组,数组的下标就是偏移量,值只有0和1,也支持一些位运算(与,或,非,异或)
-- 运用场景 可以用来记录用户的签到情况,在线状态,有没有点过赞
-- dianzan:字符串键的名称,键后面的第一个参数表示位偏移量,键后面的第二个参数表示要设置的值,返回结果是,在设置之前,该位的值
127.0.0.1:6379> setbit dianzan 0 1
(integer) 0
127.0.0.1:6379> setbit dianzan 1 1
(integer) 0
127.0.0.1:6379> setbit dianzan 1 0
(integer) 1
127.0.0.1:6379> getbit dianzan 0
(integer) 1
127.0.0.1:6379> getbit dianzan 1
(integer) 0
127.0.0.1:6379>
-- 因为bitmap是字符串类型的扩展,所以可以使用设置字符串的方式,设置值,“\xF0”十六进制 相当于11110000
127.0.0.1:6379> set dianzan "\xF0"
OK
127.0.0.1:6379> getbit dianzan 0
(integer) 1
127.0.0.1:6379> getbit dianzan 1
(integer) 1
127.0.0.1:6379> getbit dianzan 2
(integer) 1
127.0.0.1:6379> getbit dianzan 3
(integer) 1
127.0.0.1:6379> getbit dianzan 4
(integer) 0
127.0.0.1:6379> getbit dianzan 5
(integer) 0
-- 统计键中有多少个值是1
127.0.0.1:6379> bitcount dianzan
(integer) 4
-- 第一个出现0的位置
127.0.0.1:6379> bitpos dianzan 0
(integer) 4
位域 Bitfield
-- 能够将很多小的整数存储到一个较大的位图中,这样就可以更加高效地使用内存
-- 比如:在游戏中通过位域BitField来记录每个玩家在游戏中的一些关键信息(金币,等级,是否在线)
-- set:设置操作,u8:表示位字段是无符号8位整数(0-255) #0:表示从字符串键的偏移量0开始(及第一个字节的第一位)1:表示要设置的值为1.
127.0.0.1:6379> bitfield player:1 set u8 #0 1
1) (integer) 0
127.0.0.1:6379> get player:1
"\x01"
-- 上面返回的是十六进制的,可以使用下面的方法来返回十进制
127.0.0.1:6379> bitfield player:1 get u8 #0
1) (integer) 1
-- 返回值是上次设置的值
127.0.0.1:6379> bitfield player:1 set u32 #1 100
1) (integer) 0
127.0.0.1:6379> bitfield player:1 set u32 #1 50
1) (integer) 100
127.0.0.1:6379> bitfield player:1 set u32 #1 100
1) (integer) 50
127.0.0.1:6379> get player:1
"\x01\x00\x00\x00\x00\x00\x00d" -- 100转换成字符串存储就是d,('d'的ASC码就是100)
127.0.0.1:6379> bitfield player:1 get u32 #1
1) (integer) 100
-- 增加操作
127.0.0.1:6379> bitfield player:1 incrby u32 #1 100
1) (integer) 200
Redis发布订阅模式
-- 订阅消息 cxz表示一个频道名,订阅消息可以订阅多个频道,1:这是响应的第三个元素,表示订阅成功后,当前客户端订阅的频道总数。这里的 1 表示当前订阅了一个频道。
127.0.0.1:6379> subscribe cxz
1) "subscribe"
2) "cxz"
3) (integer) 1
-- 发布消息
publish cxz 没过四级
-- 发布订阅功能有一些局限性,比如无法持久化,无法记录历史消息
Redis事务
-- redis支持事务也就是在一次请求中执行多个命令,redis中的事务主要是通过MULTI和EXEC,
-- MULTL开启一个事务后,命令就会被放到一个队列中,通过EXEC命令来执行事务中的所有命令
-- 不同于关系型数据库,redis中的事务不一定全部执行成功,它的执行结果取决于事务中的命令
-- redis可以保证以下三点:
-- 1.redis在执行exec命令之前,所有的命令都会被放入到一个队列中缓存起来,不会立即执行
-- 2.在收到EXEC命令之后,事务开始执行,事务中的任何一个命令执行失败,其他命令依然会被执行,就是说不会因为某一个命令执行失败,而导致其他命令不会被执行的这样的情况发生。
-- 3.在事务执行的过程中,其他客户端提交的命令请求并不会被插入到事务的执行命令序列中
-- 客户端1
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
-- 客户端2 等客户1中的事务提交后,才能查到
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> get k2
(nil)
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379>
Redis持久化
-- redis是基于内存存储的如果没有持久化,一旦服务器重启或者断电,就会导致之前的数据都会丢失
-- redis中的持久化有两种方式
-- 一种是RDB(Redis Database)方式
-- 是指在指定时间间隔内,将内存中的数据快照写入磁盘,它是某一个时间点上数据的完整副本,可以通过配置文件中的save参数 来配置,如下面第一张图所示:,一个参数表示秒数,第二个参数表示:修改次数 。(就是在多少秒内有多少次修改才触发快照) 还可以手动设置
127.0.0.1:6379> save
OK
-- RDB更适合做备份,快照之后修改的不能找到
-- SAVE:阻塞主进程,直到 RDB 文件保存完成。
-- BGSAVE:不阻塞主进程,推荐用于手动和自动触发 RDB 持久化。
-- 在执行 BGSAVE 时,Redis 会通过 fork 创建一个子进程来处理 RDB 文件的生成。
-- 阻塞发生在 fork 阶段:fork 操作本身会阻塞主线程,但这个阻塞时间通常很短(微秒级别),具体取决于系统的负载和 内存大小。在子进程生成 RDB 文件的过程中,主线程不会被阻塞,可以继续处理客户端请求。
-- 一种是AOF (Append Only File) 方式
-- 原理:在执行写命令的时候,不仅会将命令写入到内存中,还会将命令写入到一个追加的文件中,这个文件就是AOF文件,它会以 日志的形式来记录每一个写操作,当Redis重启的时候,就会通过重新执行AOF文件中的命令,来在内存中重建整个数据库的内容。
-- 开启方式:在配置文件中将appendonly 改为yes
Redis主从复制
-- 主从复制是指将一台redis服务器的数据,复制到其他redis服务器,也叫主节点和从节点,一个主节点可以有多个从节点,一个从节点只能有一个主节点。数据的复制是单向的,只能由主节点到从节点,一般来说,主节点负责写操作,从节点负责读操作。主节点会将自己的数据变化,通过异步的方式发送给从节点,从节点接收到主节点的数据后,更新自己的数据,这样就达到了数据一致的目的。
-- INFO REPLICACTION 是 Redis 提供的一个命令,用于获取 Redis 主从复制相关的详细信息。
主节点不需要配置,因为默认的方式就是主节点的配置
Redis哨兵模式(Sentinel)
-- 主从复制中,主节点宕机了,我们需要手动将一台从节点提升为主节点,需要人工干预,这样就不能真正意义上的实现高可用
-- 哨兵会以一个独立的进程,运行在redis集群中,用来监控redis集群中的各个节点是否运行正常
-- 主要用来执行下面几个功能:
-- 1.监控
-- 通过不断的发送命令来检查Redis节点是否正常
-- 2.通知
-- 如果发现某个结点出了问题,那么哨兵就会通过发布订阅模式来通知其他节点
-- 3.自动故障转移
-- 当主节点不能正常工作的时候,哨兵会开始一个自动故障转移的操作,它会将一个从节点升级为新的主节点,然后再将其他从节点 指向新的主节点
-- 哨兵也可能产生故障,一般来说需要设置3个哨兵节点来保证高可用,这三个哨兵节点会通过选举的方式,来选出一个领导者,然后由领导者来监控其他节点 ,如果领导者挂了,会从其他哨兵节点中重新选举一个领导者
5559

被折叠的 条评论
为什么被折叠?



