一.客户端与服务端交互

  本篇简单介绍下服务器,服务器运行涉及的内部原理知识很多,主要了解Redis服务器内部要做哪些事情,需要开发人员去干预的比较少。Redis服务器负责与多个客户端建立网络连接,处理客户端发送的命令请求,在数据库中保存客户端执行命令所产生的数据,并通过资源管理来维持服务器自身的运转。本节先说客户端与服务器交互原理:服务器与客户端进行了什么交互,服务器中的各个不同组件又是如何协作的。在详细了解客户端与服务器在执行命令请求时所做的各种工作之前,先慨括看下命令请求的执行步骤过程:

    (1) 客户端向服务器发送命令请求,比如set key value 。

    (2) 服务器接收并处理客户端发来的命令请求,在数据库中进行设置操作,并产生命令回复OK。

    (3) 服务器将命令回复OK发送给客户端。

    (4) 客户端接收服务器返回的命令回复OK,并打印给用户看。

  

  1.1 客户端发送命令请求

    Redis服务器的命令请求来自Redis客户端,当用户在客户端中输入一个命令请求时,客户端会将这个命令请求转换成协议格式,然后通过连接到服务器的套接字,将协议格式的命令请求发送给服务器。

  1.2 服务端读取命令

    当客户端与服务器之间的连接套接字因为客户端的写入而变得可读时,服务器将调用命令请求处理器来执行以下操作:

(1) 读取套接字中协议格式的命令请求,并将其保存到客户端状态的输入缓冲区里面。

(2) 对输入缓冲区中的命令请求进行分析,提取出命令请求中包含的命令参数,以及命令参数的个数。分别保存到服务端记录客户端状态的argv和argc属性中。

(3) 调用命令执行器,执行客户端指定的命令。

  

  1.3 命令执行器

    (1) 查找命令实现

      命令执行器要做的第一件事就是根据客户端状态的argv[0]参数,在命令表(command table)中查找参数所指定的命令,并将找到的命令保存到客户端状态的cmd属性里面。命令表是一个字典,字典的键是一个个命令的名字,比如常见的如: get , set  ,del等命令,字典的值则是一个个redisCommand结构,每个结构记录了一个命令的实现信息。redisCommand结构的主要属性就不在此了解。

    (2) 执行预备操作

      服务器已经将执行命令所需的命令实现函数(客户端状态的cmd属性),参数(客户端状态的argv属性),参数个数(客户端状态的argc属性)都收集全了,但在真正执行命令之前,程序还要进行一些预备操作,确保命令可以正确,顺利地被执行。简单说包括:1.检查cmd属性中命令是否正确。2.参数以及参数个数是否正确。3.是否通过身份验证。4.如果打开了maxmemory功能,那么在执行命令之前,先检查服务器内存占用情况,需要时进行内存回收,以接下来的命令可以顺利执行。5.如果服务器正在进行数据载入,那么客户端发送的命令会被服务器拒绝。6.如果客户端当前正使用subscribe命令订阅频道,或者用psubscribe命令订阅模式,那么其它命令都会被服务器拒绝,8.如果客户端正在执行事务,那么服务器只会执行客户端发来的exec,discard,multi,watch命令,其它命令都会被放进事务队列中。9如果服务器开启了监视器功能,那么服务器会将要执行的命令和参数信息发送给监视器。10.如果服务器因为执行Lua脚本而超时并进入阻塞状态,那么其他命令会被服务器拒绝。注意:如果服务器是在复制或者集群模式下,预备操作会更多。完成了以上预备操作之后,服务器才会执行命令。

    (3) 执行命令实现函数操作

      服务器已经将要执行命令的实现保存到了客户端状态的cmd属性里,并将命令的参数和参数个数分别保存到了客户端状态的argv属性和argv属性中,当服务器决要执行命令时,内部只要执行以下语句就可以了:

    //clinet是指向客户端状态的指针
client->cmd->proc(client);

      当执行命令操作后,会产生相应的命令回复,比如ok, 这些回复会被保存在客户端状态的输出缓冲区里面(redisClient结构的buf属性和reply属性),之后还会为客户端的套接字关联命令回复处理器,这个处理器命令回复返回给客户端。

    (4)执行后续工作

      当执行命令实现函数之后,服务器还需要执行后续工作:1.如果服务器开启了慢查询日志功能,那么慢查询日志模块会添加一条新的慢查询日志。2.根据执行命令所耗时的时长,更新被执行命令的redisCommand结构的millisecondes属性,并将命令的redisCommand结构的calls计数器值增一。3.如果开启了AOF功能,刚执行的命令请求写入到AOF缓冲区中。4.如果有从服务器正在复制,那么该命令会传播给所有从服务器。

 当以上操作都执行完了后,服务器就可以继续从文件事件处理器中取出并处理下一个命令请求了。

二. serverCron函数

  在上节中介绍了客户端与服务端交互过程,这节了解serverCron函数执行操作,并说明这些操作对于服务器维持正常运行有何帮助。 redis服务器中的serverCron函数默认每隔100毫秒执行一次,负责管理服务器的资源,并保存执行器自身的良好运转。

  2.1 更新服务器时间缓存  

  redis服务器中有不少功能需要获取系统当前时间,每次获取系统的当前时间都需要执行一次系统调用,为了减少系统调用的执行次数,服务器状态redisServer结构的unixtime属性和mstime属性被用作当前时间的缓存。默认每隔100毫秒一次频率更新unixtime属性和mstime属性,所以这两个属性记录的时间的精确度并不高。一般用在服务器打印日志、更新服务器的LRU时钟、决定是否执行持久化任务、计算服务器上线的时间(uptime)等这类对时间精度度要求不高的功能上。对于要求精确度高的时间,会再次执行系统调用获取,一般用在为键设置过期时间、添加慢日志等功能上。

  2.2 更新LRU时钟

  LRU全称是Least Recently Used,即近期最少使用算法。用于内存数据清除方面,在第15篇中有介绍。服务器状态redisServer结构的lruclock属性保存了服务器的LRU时钟。默认每隔10秒更新一次时钟缓存。通过该算法计算一个数据库键的空转时间。

    127.0.0.1:> set msg "hello"
OK
127.0.0.1:> object idletime msg
(integer)
127.0.0.1:> object idletime msg
(integer)

  在Redis4.0版本中,感觉这个空转时钟很精确,不像默认10秒一次更新lurclock属性的值。

redis 系列20 服务器上的更多相关文章

  1. redis 系列20 服务器下

    二. serverCron函数 2.3 更新服务器每秒执行命令次数 serverCron函数中的trackOperationsPerSecond函数会以每100毫秒一次的频率执行,这个函数以抽样计算的 ...

  2. redis 系列 在 vs上 set,get 键值

    1.启动两个 cmd,一个用于打开服务,一个用于运行客户端. 详细步骤可见上一篇文章 2.下载nuget的 ServiceStack.Redis;  ,并在using中引用 ,详细步骤可见上一篇文章 ...

  3. 【目录】redis 系列篇

    随笔分类 - redis 系列篇 redis 系列27 Cluster高可用 (2) 摘要: 一. ASK错误 集群上篇最后讲到,对于重新分片由redis-trib负责执行,关于该工具以后再介绍.在进 ...

  4. Shell脚本实现超简洁的在Linux服务器上安装nginx、resin、java、tomcat、redis等程序

    说明: 用平常的方式在Linux服务器上安装程序,需要下载安装包.进入安装包位置.给安装包文件赋予可执行权限.执行安装.设置环境变量--等等一系列复杂的操作.并且如果有关联也需要一个一个的挨着安装.耗 ...

  5. 在多台服务器上简单实现Redis的数据主从复制(3)(转载)

    转载地址:http://www.cnblogs.com/liping13599168/archive/2011/04/14/2016226.html Redis的主从复制功能非常强大,一个master ...

  6. 在多台服务器上简单实现Redis的数据主从复制

          Redis的主从复制功能非常强大,一个master可以拥有多个slave,而一个slave又可以拥有多个slave,如此下去,形成了强大的多级服务器集群架构.下面我演示下怎样在多台服务器上 ...

  7. 在服务器上,配置redis可以外网访问

    首先linux开放默认端口6379打开redis配置文件redis-conf注释掉 bind 127.0.0.1(默认只有本地主要才能访问)这个注释掉现在处于受保护的状态,外网连不上,因为没有密码 在 ...

  8. redis在linux云服务器上完整的搭建步骤

    Redis的安装 搭建环境: 华为云linux服务器 Linux系统CneterOS-7.3 SSH客户端 Xshell6 安装c语言编译环境软件如下: 安装报错 然后找到了解决方法: 安装kerne ...

  9. Linux 服务器上Redis安装和配置

    1.下载安装redis 在Linux服务器上,命令行执行以下命令(cd ./usr local/src 一般源码放在这里(推荐源码安装)) wget http://download.redis.io/ ...

随机推荐

  1. Python3 文件

    f=open('C:\\Users\\fengx\\Desktop\\sharing\\test.txt') 如果打开文件的格式不匹配,可能会报如下错: >>> open('C:\U ...

  2. BZOJ2649 : riddle

    题意同3495,但是内存限制收紧了,不能采用3495的前后缀优化建图的方式. 注意到“每个集合恰好选择一个点”可以放宽成“每个集合最多选择一个点”,对于最后求出的方案里,如果某个集合没选点,任选一个就 ...

  3. USACO 邮票 Stamps

    f[x]表示组成 x 最少需要的邮票数量 一一举例 最多贴5张邮票,有三种邮票可用,分别是1分,3分,8分 组成0分需要0张邮票 ——f[0]=0 组成1分需要在0分的基础上加上一张1分邮票 ——f[ ...

  4. W3C的标准到底是啥?

    1.图片的alt="" 属性必须每张图片都加上,而且对齐属性用CSS来定义.不加不能通过XHTML 1.0的验证. 2.每个文档必须加上DTD声明. a) !DOCTYPE htm ...

  5. 一个for实现9*9乘法表

    今天看到别人一个博客提出来一个非常有趣的题目,写一个9*9的乘法表,要求只使用且仅使用一个for来实现9*9乘法表的打印.(不使用if,switch,?:)   可以用任何语言实现,下面是博主给的ja ...

  6. DevExpress内 GridControl中复选框值问题

    在DevExpress的 GridControl内的复选柜勾选后,界面看到是勾选状态,但对应的DataView的值仍未变,在以下事件内处理 在对应的DataView内的 CellValueChangi ...

  7. phantomjs api文档

    phantomjs实现了一个无界面的webkit浏览器.虽然没有界面,但dom渲染.js运行.网络访问.canvas/svg绘制等功能都很完备,在页面抓取.页面输出.自动化测试等方面有广泛的应用. 详 ...

  8. 针对Oracle用户被锁的一些相关处理方法

    当登录时被告知XXX用户被锁时,可进行以下操作: 1.用拥有dba权限的用户登录,进行解锁,先设置具体时间格式,方便后面查看被锁的具体时间: SQL> alter session set nls ...

  9. window10 Docker仓库访问

    window10 Docker仓库访问 docer官网 docker仓库 windown10 安装docker可以参考 window10安装docker 配置了加速器以后还访问不了,点击托盘处dock ...

  10. 【类与对象】--------java基础学习第六天

    类与对象 1. 对于面向对象的开发来讲也分为三个过程: OOA(面向对象分析) OOD(面向对象设计) OOP(面向对象编程) 2. 面向对象的基本特征 2.1. 封装:保护内部操作(属性,方法)不被 ...