Redis学习笔记(十一) 服务器
Redis服务器负责与多个客户端建立网络通信,处理客户端发送的命令请求,在数据库中保存客户端执行命令所产生的数据,并通过资源管理来维持服务器自身的运转。
命令请求过程(以set命令为例)
1、客户端向服务器发送命令请求 SET KEY VALUE。
Redis服务器的命令请求来自于Redis客户端,当用户从客户端键入一个命令请求时,客户端会将这个命令命令请求请求转换成协议格式,然后通过连接到服务器的套接字,将协议格式的命令请求发送给服务器。
2、服务器接收并处理客户端发送来的命令请求 SET KEY VALUE,在数据库中进行设置操作,并产生命令回复OK。
读取套接字中的协议格式命令请求,并将其保存在客户端状态的输入缓冲区中。
对输入缓冲区中的命令请求进行解析,提取出命令请求中包含的命令参数,以及命令参数的格式,分别将参数和参数个数保存到客户端状态的argv和argc属性中
调用命令执行器,执行客户端指定的命令。
命令执行器:
1、查找命令。2、执行预备操作。(检查命令、命令参数、客户端身份验证、检查服务器内存占用情况、事务、服务器状态、是否监听等)3、调用命令实现函数,产生命令回复函数,保存在客户端状态的输出缓存区4、执行后续工作:(慢查询检查记录日志;根据命令耗时更新redisCommand结构的milliseconds属性、calls计数器加1;如果开启了AOF,如果是写命令则写入到AOF缓冲区;如果有其他从服务器正在复制当前的服务器,那么服务器会将刚刚执行的命令传播给所有从服务器。)
3、服务器将命令回复OK发送为客户端。
当客户端套接字变为可写状态时,服务器会执行命令回复处理器,将保存在客户端缓冲区的命令回复发送给客户端。
4、客户端接收服务器返回的命令回复OK,并将这个回复打印给用户观看。客户端收到协议格式的命令回复后,将其转换为人类可读的格式,并打印。
serverCron函数
Redis服务器中的serverCron函数每100毫秒执行一次,这个函数负责管理服务器的资源,并保持服务器自身的良好运转。
1、更新服务器缓存时间,为减少系统调用获取当前时间的次数,服务器状态中的unixtime和mstime属性被用作当前时间的缓存:
struct redisServer{
//保存了秒级精度的当前unix时间戳
time_t unixtime;
//保存了毫秒级精度的系统当前unix时间戳
long long mstime;
//默认每10秒更新一次事件缓存,用于计算键的空转时间。
unsigned lruclock:
}
服务器只会在打印日志、更新服务器LRU始终、决定是否执行持久化任务、计算服务器上线时间这类对事件精度不高的功能上用;对于为键设置过期事件、添加慢日志这种需要高精度事件的功能来说,服务器还是会再次执行系统调用,从而获得更准确的系统当前事件。
每个Redis对象都有一个lru属性,这个lru属性保存了对象最后一次被命令访问的时间:
typedef struct redisObject{
unsigned lru:'
} robj;
serverCron函数中的trackOperationsPerSecond函数会以每100毫秒一次的频率执行,这个函数的功能以抽样计算的方式,估算并记录服务器在最近一秒钟处理的命令请求数量,这个值通过INFO status命令的instantaneous_ops_per_sec域查看。
2、更新服务器内存峰值记录:服务器状态中的stat_peak_memory属性记录服务器的内存峰值大小:
struct redisServer{
//已使用内存峰值
size_t stat_peak_memory;
}
3、处理sigterm信号
static void sigtermHandler(int sig){
//打印日志
redisLogFromHandler(REDIS_WARNING,"received sigterm,scheduling shutdown...");
//打开关闭标识
server.shutdown_asap=;
}
struct redisServer{
//serverCron函数运行时,程序灰度服务器状态的shutdown_asap属性进行检查,并根据属性值决定是否关闭服务器。
//关闭服务器的标识
//值为1时,关闭服务器
//值为0时,不做动作
int shutdown_asap;
}
4、管理客户端资源
serverCron函数每次执行都会调用clientCron函数,clientsCron函数会对一定数量的客户端进行检查:如果客户端与服务器之间的连接已经超时,那么程序释放这个客户端;如果客户端在上一次执行命令请求后,输入缓冲区的大小超过了一定的长度,那么程序会释放客户端当前的输入缓冲区,重新创建一个迷人大小的输入缓冲区,防止客户端的输入缓冲区耗费过多的资源。
5、管理数据库资源 :删除过期键,如有需要,对字典进行收缩操作。
6、执行被延迟的BGREWRITEAOF
如果BGSAVE执行期间,客户端发来BGREWRITEAOF命令,则需要延迟到BGSAVE命令执行完成后。
7、检查持久化操作运行状态
服务器状态使用rdb_child_pid\aof_child_pid属性记录执行BGSAVe命令和BGREWRITEAOF命令的子进程ID,用于检查命令是否正在执行
struct redisServer{
//记录执行BGSAVE命令的紫禁城,如果没有执行则为-1
pid_t rdb_child_pid;
//记录执行BGREWRITEAOF命令的子进程ID,没执行则为-1
pid_t aof_child_pid;
}
8、将AOF缓冲区中的内容写入AOF文件
9、关闭异步客户端(检查输出缓冲区大小)
10、增加cronloops计数器的值(没执行serverCron函数N次就执行一次指定的代码)
初始化服务器
1、初始化服务器状态结构,创建一个struct redisServer类型的实例变量server作为服务器的状态。
initServerConfig函数完成的主要工作:
设置服务器运行ID
设置服务器的默认运行频率
设置服务器的默认配置文件路径
设置服务器的运行架构
设置服务器的默认端口号
设置服务器默认RDB持久化条件和APF持久化条件
初始化服务器LRU时钟
创建命令表
2、载入配置项修改默认的配置。
3、初始化服务器数据结构
在执行initServerConfig函数初始化server状态时,程序只创建命令表一个数据结构,服务器在次数初始化其他数据结构:
server.clients链表,记录所有与服务器相连接的客户端状态
erver.db数组,包含服务器的所有数据库。
保存频道订阅信息的server.pubsub_channels字典以及保存模式订阅信息的server_publsub_patterns链表。
执行Lua脚本的Lua环境 server.lua;
用于保存慢查询日志的server.slwlog链表
除了初始化数据结构之外,initServer还进行了一些非常重要的设置操作:
为服务器设置进程信号处理器。
创建共享对象。
打开服务器的监听端,并未监听套接字关联连接应答事件处理时,等待服务器正式运行时接收客户端连接。
为serverCron函数创建时间事件,等待服务器正式运行时,执行serverCron函数。
如果AOF持久化功能打开,那么打开现有的AOF文件,如果文件不存在则创建新的AOF文件
初始化服务器的后台I/O模块,为将来的I/O操作做准备。
执行完以上内容那么你就看到了熟悉的画面:
4、还原数据库装填
在完成对服务器状态server变量的初始化后,服务器需要载入RDB文件或者AOF文件,并根据文件记录的内容还原数据库状态
5、执行事件循环
到此服务器的初始化工作圆满完成,服务器现在开始可以接收客户端的连接请求,并处理客户端发来的命令请求。
写到这里,非常有冲动写一下.net 程序初始化以及运行过程服务端做了那些事情,着手准备!
每天学一点,总会有收获。
说明:尊重作者知识产权,文中内容参考《Redis设计与实现》,仅在此做学习与大家分享。
Redis学习笔记(十一) 服务器的更多相关文章
- redis 学习笔记(6)-cluster集群搭建
上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞shardi ...
- Redis学习笔记~目录
回到占占推荐博客索引 百度百科 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...
- Redis学习笔记4-Redis配置详解
在Redis中直接启动redis-server服务时, 采用的是默认的配置文件.采用redis-server xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务.按照本Redi ...
- Redis学习笔记一:数据结构与对象
1. String(SDS) Redis使用自定义的一种字符串结构SDS来作为字符串的表示. 127.0.0.1:6379> set name liushijie OK 在如上操作中,name( ...
- Redis学习笔记之ABC
Redis学习笔记之ABC Redis命令速查 官方帮助文档 中文版本1 中文版本2(反应速度比较慢) 基本操作 字符串操作 set key value get key 哈希 HMSET user:1 ...
- (转)redis 学习笔记(1)-编译、启动、停止
redis 学习笔记(1)-编译.启动.停止 一.下载.编译 redis是以源码方式发行的,先下载源码,然后在linux下编译 1.1 http://www.redis.io/download 先 ...
- Redis学习笔记(二)Redis支持的5种数据类型的总结之String和Hash
引言 在Redis学习笔记(一)中我们已经会安装并且简单使用Redis了,接下来我们一起来学习下Redis支持的5大数据类型. 简介 Redis是REmote DIctionary Server(远程 ...
- Redis学习笔记(3)——Redis的命令大全
Redis是一种nosql数据库,常被称作数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted se ...
- Redis学习笔记(1)——Redis简介
一.Redis是什么? Remote Dictionary Server(Redis) 是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value ...
- redis 学习笔记-cluster集群搭建
一.下载最新版redis 编译 目前最新版是3.0.7,下载地址:http://www.redis.io/download 编译很简单,一个make命令即可,不清楚的同学,可参考我之前的笔记: red ...
随机推荐
- php中垃圾回收机制
php中垃圾回收机制 我们可能在开发中经常会听到gc,是的gc就是垃圾回收容器,全称Garbage Collection. 此篇文章中“垃圾”的概念:如果一个变量容器能被减少到0,说明他就已经没有被引 ...
- 0day堆(1)堆的管理策略
基本概念 堆块:堆区内存的基本单位 包括两个部分:块首,块身 块首:标识这个堆块自身的信息:如大小,是否被占用等 块身:分配给用户使用的数据区 堆表:一般位于堆区的起始位置,用于索引堆区所有堆块的信息 ...
- mysql-管理命令【创建用户、授权、修改密码、删除用户和授权、忘记root密码】
一.创建用户 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 关键参数说明: username - 创建登录用户名, host ...
- 【JAVA基础】07 面向对象2
1. 代码块的概述和分类 面试的时候会问,开发不用或者很少用 代码块概述 在Java中,使用 {} 括起来的代码被称为代码块. 代码块分类 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态 ...
- Element UI表格组件技巧:如何简洁实现跨页勾选、跨页统计功能
业务场景 在使用Element UI的Table组件时,常常面对这样的业务需求: 表格数据的每一项都要提供勾选框,当切换分页时,能够记忆所有页面勾选的数据,以实现批量提交不同页面勾选数据的功能.并且, ...
- for-loop 与 json.Unmarshal 性能分析概要
原文地址:for-loop 与 json.Unmarshal 性能分析概要 前言 在项目中,常常会遇到循环交换赋值的数据处理场景,尤其是 RPC,数据交互格式要转为 Protobuf,赋值是无法避免的 ...
- 关于Python的JSON
1.json模块load/loads.dump/dumps区别:(摘自这里) 实际上json就是python字典的字符串表示,但是字典作为一个复杂对象是无法直接转换成定义它的代码的字符串,python ...
- Hadoop学习笔记(三) ——HDFS
参考书籍:<Hadoop实战>第二版 第9章:HDFS详解 1. HDFS基本操作 @ 出现的bug信息 @-@ WARN util.NativeCodeLoader: Unable to ...
- 背英语单词很困难,不妨学习一下词根词缀吧(每天10个词根、词缀)Part 3
1.ir- 不,向内 例词: irregular=ir(不)-regular(规则的)=不规则的 irrigate=ir(向内)-rigate(浇水)=灌溉 2. kilo- 千 例词: kilogr ...
- CF思维联系– CodeForces -CodeForces - 992C Nastya and a Wardrobe(欧拉降幂+快速幂)
Nastya received a gift on New Year - a magic wardrobe. It is magic because in the end of each month ...