带你走进Redis的世界 - Redis的客户端服务端交互

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 带你走进Redis的世界 - Redis的客户端服务端交互

前言

Redis实例运行于单独的进程之中,应用系统和Redis通过Redis协议进行交互。在协议允许的范围内,客户端与服务器可以实现多种典型的交互模式:串行的请求/响应模式、双工的请求/响应模式(Pipeline)、原子化的批量请求/响应模式(事务)、发布/订阅模式、脚本化的批量执行(脚本模式)

双工模式,包括半双工、全双工

半双工:在同一时刻,A 、B通讯双方只能单方向传输信息,A -> B 或者 B -> A

全双工:在任意时刻,A、B通讯双方都能互传信息,支持任意时刻的A -> B ,B -> A


客户端/服务器协议

Redis的交互协议包括:

  • 网络模型 数据交互的组织方式
  • 序列化协议 数据本身序列化
1. 网络交互

Redis协议位于TCP层之上,即客户端和Redis实例保持双工的连接。客户端与服务端交互的内容,是序列化后的相应类型的协议数据,服务器端为每个客户端建立对应的连接,在应用层维护一系列的状态保存到连接中。连接之间没有相互关联性。在Redis中,连接通过redisClient结构体实现。

2. 序列化协议

在Redis中,协议数据分为不同的类型,每种类型的数据均以CRLF(\r\n)结束,通过数据首字符区分类型。

  • inline command

这类数据表示Redis命令,首字符为Redis命令名的字符,格式为command str

如,keys * ,首字符为k,表示Redis查找所有的匹配的key

  • simple string

首字符为+,后续字符为string的内容,且该string不能包含\r \n 两个字符;最后仍以\r\n结束

如,+OK\r\n 表示新增OK这个string数据

  • bulk string

对于string类型本身内容中包含了\r \n的情况,simple string不再适用

解决方案可以包括两种,转义字符和长度自描述。Redis采用的是长度自描述,称为Bulk string

bulk string 首字符为$ ,紧随之后是string数据长度,\r\n之后紧跟着string的内容本身,可以允许包含\r或者\n特殊字符,最后仍以\r\n结束

如 $12\r\nhello\r\nworld\r\n

对于“”字符串和null通过$之后数字长度区分

  • “$0\r\n\r\n”,代表空字符串
  • "$-1\r\n"代表null
  • error

对于服务端返回内容,客户端需要识别是正确内容还是异常响应。异常信息即error类型数据,在Redis中首字符“-”表示

如“-ERR unknown command'foobar'\r\n“ 表示一个错误,和一个错误信息

  • integer

首字符“:”开头,紧跟着整型数字本身,最后\r\n结尾

  • array

数组以首字符“*”开头,紧跟着数组的长度,\r\n之后为数组中每个元素的序列化数据。

如,*2\r\n+abc\r\n:9\r\n 代表长度为2的数组,["abc",9]

数组长度为0或-1代表空数组或者null

  • C/S两端使用的协议数据类型

客户端发送给服务器端的类型为:inline command 有bulk string组成的array

由服务器端发送给客户端的类型为除了inline command 之外的所有类型,根据客户端命令或者交互模型不同进行确定,如:

  • 请求/响应模式下,对客户端发送的EXISTS KEY1 返回integer型数据
  • 发布/订阅模式下,为channel 订阅者推送的消息,采用array型数据


请求/响应模式

同一连接,请求/响应模式如下:

交互方向:客户端发送请求数据,服务器发送响应数据

对应关系:每一个请求数据其且仅有一个对应的响应数据

时序:响应数据的发送发生在“服务器完全接收到其对应的请求数据”之后

1.串行化实现

Redis对单个请求的处理时间通常比局域网延迟小一个数量级,因此串行化模式下,单连接的大部分时间都处于网络等待,没有充分利用服务器的处理能力。

2.pipeline实现

pipeline的实现取决于客户端,需要考虑:

  • 通过批量请求发送还是异步化请求发送实现
  • 非异步化的批量发送需要考虑每个批次的数据量,避免连接的buffer满后死锁
  • 对使用者如何封装接口,使得使用pipeline简单


事务模式

当需要将批量执行的语句原子化,需要引入redis的事务模式

image.png

一次事务中多条命令以原子化方式执行,不同事务的命令相互时序不再交叉

1.入队/执行分离的事务原子性

入队阶段:客户端将请求发送到服务端之后,暂存在连接对象对应的请求队列中

执行阶段:发送完一个批次的所有请求后,redis服务器一次执行连接对象队列中的所有请求

执行过程,redis不再执行其余连接请求。

2.事务一致性

当入队阶段出现错误,不执行后续的执行exec,不会对数据实际产生影响

当执行阶段已经开始,其中一条请求执行失败,后续请求会继续执行,返回客户端的array型响应中标记出错的结果,redis本身不包含回滚机制

3.事务的只读操作

入队模式下,所有的操作都没有真正执行,仅返回是否入队成功。此时,以A账号向B账号转账说明:

100 <= get a
100 <= get b
ok <= multi
queued <= set b 110
queued <= set a 90

如果客户端2,中间对a或者b有所改变,那么最终一致性就会被破坏

4.乐观所得可串行化事务隔离

正如上述所说,不同事务的命令相互时序不再交叉,Redis通过watch机制实现乐观锁,解决事务一致性问题

  • 将本次事务涉及的所有key注册为观察模式,假设此时逻辑时间为tstart
  • 执行只读操作
  • 根据只读操作结果组装写操作命令并发送到服务器端入队
  • 发送原子化的批量执行命令,试图执行连接的请求队列中的命令,此时逻辑时间为tcommit

存在两种情况:

假设注册的key有一个或多个,在tstart和tcommit之间被修改,则原子化批量执行命令,拒绝执行;

否则执行所有队列中请求

5.事务实现

事务实现通过redisObject对象进行相关设置

6.事务交互模式

通过watch机制,保证了不存在数据不一致问题,执行器是单线程,保证所有的写操作都是通过串行方式实现串行化

脚本模式

事务模式,会有一定的局限,redis允许客户端向服务器提交一个脚本,来编排业务事务多个redis操作,

1.脚本交互模式
  • 客户端发送eval lua_script_string 2 key1 key2 first second 给服务端
  • 服务端解析lua_script_string 根据string内容通过sha1计算出sha值,存放到redisServer对象的lua_script 成员变量中
  • 服务器端原子化通过内置lua执行脚本
  • 执行完成后,将lua结果转为redis类型返回给客户端
2.script特性

脚本包含以下特性:

  • 每一个提交的脚本,常驻不会消失,除非显式通过flush命令清理
  • script在实例的主备间可以通过script重放和cmd重放实现复制
  • 执行过的script之后,可以通过sha指定,不用重复发内容到服务端


发布/订阅模式

redis提供一种模式,一个客户端触发,多个客户端被动接受,称为发布/订阅模式

1.发布/订阅交互模式

该模式如下所述:

1)角色关系

  • 客户端分为发布者和订阅者两种角色
  • 发布端和订阅者通过channel关联

2)交互方向

  • 发布者和redis服务器的交互认为请求/响应模式
  • 服务端向订阅者发送数据,推送
  • 时序:服务器收到发布者消息之后
2.两类channel

普通channel:明确定义的channel

pattern channel:模糊匹配的channle

3.订阅实现
typedef struct redisServer {
...
dict *pubsub_channels;
list *pubsub_patterns;
...
}

通过维护指针链表来实现。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
NoSQL Redis 数据安全/隐私保护
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
文章提供了Redis最流行的图形化界面工具Another Redis Desktop Manager的下载及使用教程,包括如何下载、解压、连接Redis服务器以及使用控制台和查看数据类型详细信息。
132 6
Redis 最流行的图形化界面下载及使用超详细教程(带安装包)! redis windows客户端下载
|
1月前
|
NoSQL Redis 数据库
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
文章提供了Redis图形化界面工具的下载及使用教程,包括如何连接本地Redis服务器、操作键值对、查看日志和使用命令行等功能。
124 0
Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
|
3月前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
173 3
|
26天前
|
NoSQL 网络协议 算法
Redis 客户端连接
10月更文挑战第21天
27 1
|
1月前
|
存储 消息中间件 NoSQL
Redis 入门 - C#.NET Core客户端库六种选择
Redis 入门 - C#.NET Core客户端库六种选择
60 8
|
2月前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
3月前
|
NoSQL 网络协议 Linux
【AKS+Redis】AKS中客户端(ioredis)遇见Azure Redis服务Failover后链接中断的可能性
【AKS+Redis】AKS中客户端(ioredis)遇见Azure Redis服务Failover后链接中断的可能性
|
3月前
|
NoSQL 网络协议 Linux
【Azure Redis】Lettuce客户端遇见连接Azure Redis长达15分钟的超时
【Azure Redis】Lettuce客户端遇见连接Azure Redis长达15分钟的超时
|
3月前
|
NoSQL 网络协议 Linux
【Azure Redis】Redis客户端出现15分钟的超时异常
【Azure Redis】Redis客户端出现15分钟的超时异常
|
3月前
|
缓存 监控 NoSQL
【Azure Redis 缓存】Azure Redis出现了超时问题后,记录一步一步的排查出异常的客户端连接和所执行命令的步骤
【Azure Redis 缓存】Azure Redis出现了超时问题后,记录一步一步的排查出异常的客户端连接和所执行命令的步骤
下一篇
无影云桌面