Redis的IO多路复用和多线程特性会破坏分布式锁的原子性吗?(中)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis的IO多路复用和多线程特性会破坏分布式锁的原子性吗?

3.3 命令执行:processCommand

实现在server.c,实际执行命令前的主要逻辑:

  1. processCommand调用moduleCallCommandFilters,将Redis命令替换成module想替换的命令
  2. processCommand判断当前命令是否为quit命令并做相应处理

image.png

3.processCommand调用lookupCommand,在全局变量server的commands成员变量中查找相关命令

image.png



全局变量server的commands成员变量是个哈希表,定义在redisServer结构体:

image.png

commands成员变量的初始化是在initServerConfig,调用dictCreate完成哈希表创建,再调用populateCommandTable将Redis提供的命令名称和对应的实现函数,插入哈希表。

image.png

而这其中的populateCommandTable使用了redisCommand结构体数组redisCommandTable。


redisCommandTable数组是在server.c文件中定义的,它的每一个元素是一个redisCommand结构体类型的记录,对应了Redis实现的一条命令。也就是说,redisCommand结构体中就记录了当前命令所对应的实现函数是什么。


如下代码展示GET、SET等命令信息,实现函数分别是getCommand,setCommand:

1.png

所以lookupCommand会根据解析的命令名称,在commands对应的哈希表中查找相应命令。


那么,一旦查到对应命令后,processCommand函数就会进行多种检查,比如命令的参数是否有效、发送命令的用户是否进行过验证、当前内存的使用情况,等等。这部分的处理逻辑比较多,你可以进一步阅读processCommand函数来了解下。


这样,等到processCommand对命令做完各种检查后,就开始执行命令,会判断当前客户端是否有CLIENT_MULTI标记:


  • 若有,说明要处理Redis事务相关命令

就要按事务要求,调用queueMultiCommand:将命令入队保存,等待后续再一把梭处理。

  • 若无,无关事务特性

processCommand调用call:实际执行命令。call函数执行命令是通过调用命令本身,即redisCommand结构体中定义的函数指针完成。每个redisCommand结构体中都定义了其对应实现函数,在redisCommandTable数组可查到。


分布式锁的加锁操作就是使用SET命令实现的,所以来看SET命令为例,来看一个命令实际执行过程。


SET命令对应实现函数setCommand:首先会判断命令参数,如是否带有NX、EX、XX、PX等可选项,若有,就会记录这些标记。


然后,setCommand会调用setGenericCommand:根据setCommand记录的命令参数标记,进行相应处理。如命令参数中有NX,则setGenericCommand会调用lookupKeyWrite,查找要执行SET命令的key是否已存在。


若K已存在,则setGenericCommand会调用addReply,返回NULL,正符合分布式锁的语义。


image.png

image.png

若SET命令可正常执行,即:

  • 命令带NX选项但K并不存在
  • 或带有XX选项但K已存在


这样setGenericCommand就会调用setKey完成KV对的实际插入:

setKey(c->db,key,val);

然后,若命令设置了TTL,setGenericCommand还会调用setExpire函数设置过期时间。最后,setGenericCommand函数会调用addReply函数,将结果返回给客户端,如下所示:

addReply(c, ok_reply ? ok_reply : shared.ok);

SET命令执行流程:

1.png

无论:

  • 在命令执行过程中,发现不符合命令的执行条件
  • 或是命令能成功执行


addReply函数都会被调用以返回结果。所以,这就进入命令处理过程的最后一个阶段:结果返回阶段。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
25天前
|
消息中间件 存储 NoSQL
剖析 Redis List 消息队列的三种消费线程模型
Redis 列表(List)是一种简单的字符串列表,它的底层实现是一个双向链表。 生产环境,很多公司都将 Redis 列表应用于轻量级消息队列 。这篇文章,我们聊聊如何使用 List 命令实现消息队列的功能以及剖析消费者线程模型 。
69 20
剖析 Redis List 消息队列的三种消费线程模型
|
5天前
|
NoSQL 网络协议 Unix
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
17 1
|
9天前
|
消息中间件 NoSQL Java
面试官:谈谈你对IO多路复用的理解?
面试官:谈谈你对IO多路复用的理解?
23 0
面试官:谈谈你对IO多路复用的理解?
|
11天前
|
网络协议 Java Linux
高并发编程必备知识IO多路复用技术select,poll讲解
高并发编程必备知识IO多路复用技术select,poll讲解
|
6天前
|
存储 消息中间件 NoSQL
Redis的单线程设计之谜:高性能与简洁并存
Redis的单线程设计之谜:高性能与简洁并存
17 0
|
2月前
|
NoSQL Redis 数据库
Redis AOF重写问题之同一数据产生两次磁盘IO如何解决
Redis AOF重写问题之同一数据产生两次磁盘IO如何解决
Redis AOF重写问题之同一数据产生两次磁盘IO如何解决
WXM
|
2月前
|
存储 缓存 算法
IO/线程的零拷贝
服务器在提供文件传输功能时,传统实现方式是通过读取磁盘文件内容,将其加载到用户空间的缓冲区,再通过网络 API 发送至客户端,这个过程涉及多次上下文切换和内存拷贝,导致性能下降。
WXM
41 12
|
3月前
|
消息中间件 缓存 NoSQL
Redis快速度特性及为什么支持多线程及应用场景
Redis快速度特性及为什么支持多线程及应用场景
77 11
|
2月前
|
缓存 开发框架 NoSQL
【Azure Redis 缓存】Azure Redis 异常 - 因线程池Busy而产生的Timeout异常问题
【Azure Redis 缓存】Azure Redis 异常 - 因线程池Busy而产生的Timeout异常问题
|
3月前
|
存储 缓存 NoSQL
Redis性能优化问题之优化 Redis fork 耗时严重的问题,如何解决
Redis性能优化问题之优化 Redis fork 耗时严重的问题,如何解决
下一篇
无影云桌面