学习 Redis - 2. 场景操作

2021-12-06 15:09:10 浏览数 (1)

前面学习了一些基础的命令,以及对常用数据类型的命令的学习。

今天学习下redis的常见特性。

Redis 发布订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

Redis 客户端可以订阅任意数量的频道

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

举个例子:

  • 开启Redis服务 redis-server,开启2个redis-cli客户端分别为A和B redis-clil --raw
  • 在A客户端输入 SUBSCRIBE chasays
  • 在B客户端输入 PUBLISH chasays "client2 publish mesg1"
  • 在A就可以看到B 发布的消息

Redis 事务

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。 一个事务从开始到执行会经历以下三个阶段:
  1. 开始事务。
  2. 命令入队。
  3. 执行事务。

举个例子:

它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

代码语言:javascript复制
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set task1 "this is task1"
QUEUED
127.0.0.1:6379> get task1
QUEUED
127.0.0.1:6379> sadd tag "tag1" "tag2" "tag3"
QUEUED
127.0.0.1:6379> SMEMBERS tag
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "this is task1"
3) (integer) 3
4) 1) "tag1"
   2) "tag3"
   3) "tag2"
127.0.0.1:6379>

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的

事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

所以事务就是,不管其中一条失败了,不影响其他的操作。

Redis 脚本

Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。

基本语法:

EVAL script numkeys key [key ...] arg [arg ...]

代码语言:javascript复制
127.0.0.1:6379> EVAL "return 123" 1 key1
(integer) 123

Redis 连接

Redis 连接命令主要是用于连接 redis 服务

举个例子:

代码语言:javascript复制
127.0.0.1:6379> AUTH redis
(error) ERR AUTH <password> called without any password configured for the default user. Are you sure your configuration is correct?
127.0.0.1:6379> echo "hello world"
"hello world"
127.0.0.1:6379> ping  # 查看是否允许
PONG # ok
Could not connect to Redis at 127.0.0.1:6379: Connection refused # fail

Redis 服务器

Redis 服务器命令主要是用于管理 redis 服务

  • save 保存数据到硬盘
  • sync 用于复制功能(replication)的内部命令
  • flushall 删除所有数据库的所有key
  • flushdb 删除当前数据库的所有key

举个例子:

代码语言:javascript复制
127.0.0.1:6379> CLIENT list
id=4 addr=127.0.0.1:51449 fd=8 name= age=25 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default
127.0.0.1:6379> CLIENT GETNAME

127.0.0.1:6379> TIME
1605966135
812269
127.0.0.1:6379> SYNC
Entering replica output mode...  (press Ctrl-C to quit)
SYNC with master, discarding 222 bytes of bulk transfer...
SYNC done. Logging commands from master.
"PING"
"PING"

Redis GEO

Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。

常见的方法有:

  • geoadd:添加地理位置的坐标。 语法 GEOADD key longitude latitude member [longitude latitude member ...]
  • geopos:获取地理位置的坐标。 语法 GEOPOS key member [member ...]
  • geodist:计算两个位置之间的距离。 语法 GEODIST key member1 member2 [m|km|ft|mi]
  • georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。 语法 GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key]
  • georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。 语法 GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [ST
  • geohash:返回一个或多个位置对象的 geohash 值。 语法 GEOHASH key member [member ...]

Redis 流

Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。

如下所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容:

上图解析:

  • Consumer Group :消费组,使用 XGROUP CREATE 命令创建,一个消费组有多个消费者(Consumer)。
  • last_delivered_id :游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。
  • pending_ids :消费者(Consumer)的状态变量,作用是维护消费者的未确认的 id。 pending_ids 记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符)。

每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。

消息离队的相关命令:

  • XADD - 添加消息到末尾
  • XTRIM - 对流进行修剪,限制长度
  • XDEL - 删除消息
  • XLEN - 获取流包含的元素数量,即消息长度
  • XRANGE - 获取消息列表,会自动过滤已经删除的消息
  • XREVRANGE - 反向获取消息列表,ID 从大到小
  • XREAD - 以阻塞或非阻塞方式获取消息列表
代码语言:javascript复制
27.0.0.1:6379> XADD stream1 * name 1 2 3
1605966736739-0
127.0.0.1:6379> XADD stream1 * key1 key2 key3
ERR wrong number of arguments for XADD

127.0.0.1:6379> XADD stream1 * key1 value1 key2 value2
1605966769163-0
127.0.0.1:6379> XLEN stream1
2
127.0.0.1:6379> XRANGE stream1 -  
1605966736739-0
name
1
2
3
1605966769163-0
key1
value1
key2
value2

这次命令有点多, 主要是特殊的场景用什么样的redis功能,比如publish和stream,以及事务。这几个是比较实用。

0 人点赞