【Redis源码】Redis命令INCR、DECR、INCRBY、DECRBY学习(二)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 【Redis源码】Redis命令INCR、DECR、INCRBY、DECRBY学习(二)

前言:

该篇内容为我对redis的学习记录,欢迎指正批评。文中只是放了部分调试内容,完整的可以根据流程图跟踪。

一.redis incr命令调用流程

DECR和INCR和类似只是一个是增加一个是减少。其余两个命令也大同小异;

二.源码分析

4个命令相应源码,t_string.c中:


voidincrCommand(client *c) {
   incrDecrCommand(c,1);      //incr每次增加1 命令原型:incr test1
}

voiddecrCommand(client *c) {
   incrDecrCommand(c,-1);     //incr每次减少1 命令原型:decr test1
}

voidincrbyCommand(client *c) {
   longlong incr;

   if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return;   //获得第二个,增加数量
   incrDecrCommand(c,incr);    //incrby每次增加输入的数 命令原型增加100:incrby test1 100
}

voiddecrbyCommand(client *c) {
   longlong incr;

   if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return;  //获得第二个,减少数量
   incrDecrCommand(c,-incr);   //decrby每次加少输入的数 命令原型减少100:decrby test1 100
}

incrDecrCommand函数源码 ,t_string.c中:

voidincrDecrCommand(client *c, longlong incr) {
   longlong value, oldvalue;
   robj *o, *new;

   o = lookupKeyWrite(c->db,c->argv[1]);         //查找有没有对应的键值
   if (o != NULL && checkType(c,o,OBJ_STRING)) return;      //判断类型
   if (getLongLongFromObjectOrReply(c,o,&value,NULL) != C_OK) return;  //获得键值中的数据

   oldvalue = value;
   if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||
       (incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {   //判断不能不能越界,超出long long范围
       addReplyError(c,"increment or decrement would overflow");
       return;
   }
   value += incr;   //与操作数相加

   /*
   判断是否大于对象共享整数,value是否在long只最小到最大之间。共享对象整数为大于10000
   */

   if (o && o->refcount == 1 && o->encoding == OBJ_ENCODING_INT &&
       (value < 0 || value >= OBJ_SHARED_INTEGERS) &&
       value >= LONG_MIN && value <= LONG_MAX)                    
   {
       new = o;
       o->ptr = (void*)((long)value);
   } else {
       new = createStringObjectFromLongLong(value); //根据数值创建一个long long的robj结构指针
       if (o) {
           dbOverwrite(c->db,c->argv[1],new);     //重写字典
       } else {
           dbAdd(c->db,c->argv[1],new);           //添加字典
       }
   }
   signalModifiedKey(c->db,c->argv[1]); //通知修改了key
   notifyKeyspaceEvent(NOTIFY_STRING,"incrby",c->argv[1],c->db->id); //发送事件通知
   server.dirty++;
   addReply(c,shared.colon);
   addReply(c,new);
   addReply(c,shared.crlf);
}


三.调试信息(看图片可能看不懂,先看流程图,根据图片再看)

下一个call断点,然后进入incrCommand

打印命令信息,以及调用栈

获得long long对象调试

增加数据部分调试

有键值是覆盖写入


相关实践学习
基于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
相关文章
|
3天前
|
NoSQL 数据可视化 Java
rodert单排学习redis进阶【白银一】
rodert单排学习redis进阶【白银一】
9 0
|
3天前
|
NoSQL Redis 数据库
rodert单排学习redis进阶【青铜】2
rodert单排学习redis进阶【青铜】
9 0
|
4天前
|
缓存 NoSQL Java
rodert单排学习redis进阶【青铜】1
rodert单排学习redis进阶【青铜】
13 0
|
4天前
|
存储 缓存 NoSQL
rodert单排学习redis入门【黑铁】2
rodert单排学习redis入门【黑铁】
8 0
|
4天前
|
存储 缓存 NoSQL
rodert单排学习redis入门【黑铁】1
rodert单排学习redis入门【黑铁】
12 0
|
11天前
|
NoSQL Java 网络安全
Redis在java(Maven)中使用,常用基本命令大全,最全Termius怎么进行端口映射(MAC系统最简单教学)
Redis在java(Maven)中使用,常用基本命令大全,最全Termius怎么进行端口映射(MAC系统最简单教学)
|
11天前
|
缓存 NoSQL 关系型数据库
Redis第二课,1.set key value(设置对应的key和value)2.get key(得到value值)Redis全局命令(支持很多的数据结构)3.keys(用来查询当前
Redis第二课,1.set key value(设置对应的key和value)2.get key(得到value值)Redis全局命令(支持很多的数据结构)3.keys(用来查询当前
|
11天前
|
NoSQL Redis 索引
Redis的基础命令集详解
Redis的基础命令集详解
10 0
|
13天前
|
存储 消息中间件 缓存
Redis基础命令集详解
Redis基础命令集详解
11 0
|
13天前
|
NoSQL Redis Python
python中使用redis的常用命令
Python中使用Redis的常用命令。redis-py库提供了一个简单而强大的接口来执行Redis的各种操作。你可以根据需要选择合适的命令来操作Redis数据结构。
14 0