灵犀科技 网站开发佼佼者,网站开发 费用,做网络销售都做什么网站,代码高亮wordpressredis(一)内部机制的介绍和启动过程redis的基本介绍redis服务端redis客户端redis的持久化redis中的文件事件和时间时间redis的启动过程redis的基本介绍redis是一种非关系型数据库#xff0c;采用key#xff0c;value的形式来存储数据。key是二进制数据#xff0c;对于value的…redis(一)内部机制的介绍和启动过程redis的基本介绍redis服务端redis客户端redis的持久化redis中的文件事件和时间时间redis的启动过程redis的基本介绍redis是一种非关系型数据库采用keyvalue的形式来存储数据。key是二进制数据对于value的数据类型redis支持string、hash、list、set、sorted set五种类型。对于单个redis实例内部使用多线程通信但是对外采用RESP单线程通信协议在TCP层通过二进制方式进行传输数据单线程采用同步的请求方式。redis服务端redis服务端内部结构为struct redisServer和struct redisDb。redis中默认16个数据库可以通过配置来修改数据库数量每一个数据库对应一个redisDb。数据库之间的数据是相互独立的。查询数据的时候可以通过select指定具体某个数据库。1 struct redisServer {2 int dbnum;//服务器的数据库数量值由服务器配置的“databases”选项决定默认为163 redisDb *db;//数组保存着服务器中的所有数据库45 list *clients;//一个链表保存了所有客户端状态每个链表元素都是“redisClient”结构67 time_t unixtime;//保存秒级精度的系统当前UNIX时间戳减少获取系统当前时间的系统调用次数100毫秒更新一次8 long long mstime;//保存毫秒级精度的系统当前UNIX时间戳9 unsigned lruclock;//默认每10秒更新一次用于计算数据库键的空转时长数据库键的空转时长 服务器的“lruclock”属性值 - 数据库键值对象的“lru”属性值1011 long long ops_sec_last_sample_time;//上一次进行服务器每秒执行命令数量抽样的时间12 long long ops_sec_last_sample_ops;//上一次进行服务器每秒执行命令数量抽样时服务器已执行命令的数量13 long long ops_sec_samples[REDIS_OPS_SEC_SAMPLE];//环形数组每个元素记录一次服务器每秒执行命令数量抽样结果估算服务器在最近一秒钟处理的命令请求数量(数组长度默认为16100毫秒更新一次)14 int ops_sec_idx;//ops_sec_samples数组的索引值每次抽样后值增1等于16时重置为01516 size_t stat_peak_memory;//已使用内存峰值1718 int shutdown_asap;//关闭服务器的标识1表示关闭0不关闭1920 pid_t rdb_child_pid;//记录执行BGSAVE命令的子进程的ID-1表示服务器没有正在执行BGSAVE21 pid_t aof_child_pid;//记录执行BGREWRITEAOF命令的子进程的ID-1表示服务器没有正在执行BGREWRITEAOF22 int aof_rewrite_scheduled;//1表示有BGREWRITEAOF命令被延迟了(服务器执行BGSAVE期间收到的BGREWRITEAOF会被延迟到BGSAVE执行完成之后执行)23 struct saveparam *saveparams;//记录了自动保存条件的数组(执行BGSAVE的条件)24 long long dirty;//修改计数器(上一次执行BGSAVE之后已经产生了多少修改)25 time_t lastsave;//上一次执行自动保存操作(BGSAVE)的时间26 sds aof_buf;//AOF缓冲区2728 int cronloops;//serverCron函数的运行次数计数器2930 lua;//用于执行Lua脚本的Lua环境31 redisClient *lua_client;//Lua脚本的伪客户端在服务器运行的整个生命周期一直存在直至服务器关闭才会关闭32 dict *lua_scripts;//字典记录所有载入的Lua脚本键为某个Lua脚本的SHA1校验和值为对应的Lua脚本33 dict *repl_scriptcache_dict;//字典记录已经传播给所有从服务器的所有Lua脚本键为脚本的SHA1校验和值为NULL用于EVALSHA1命令的复制3435 long long slowlog_entry_id;//下一条慢查询日志的ID36 list *slowlog;//保存了所有慢查询日志的链表37 long long slowlog_log_slower_than;//服务器配置“slowlog-log-slower-than”选项的值表示查询慢于多少微秒便记录慢查询日志38 unsigned long slowlog_max_len;//服务器配置“slowlog-max-len”选项的值表示服务器最多保存多少条慢查询日志记录若超出最久的记录会被覆盖3940 monitors;//链表监视器客户端列表4142 dict *pubsub_channels;//字典保存所有频道的订阅关系键为某个被订阅的频道值为链表记录了所有订阅这个频道的客户端43 list *pubsub_patterns;//链表保存所有模式的订阅关系每个链表节点都包含了订阅的客户端和被订阅的模式44 };struct redisDb {dict*dict;//数据库键空间字典保存数据库中所有的键值对dict *expires;//过期字典保存数据库中所有键的过期时间dict *watched_keys;//字典正在被WATCH命令监视的键};redisDb中三个字典中的key共享对象value值不一样。对于过期的键redis采用惰性删除和定时删除相结合的方式惰性删除指执行之前会查看这个key是否过期定时删除值一段时间之后分多次遍历数据库每次只删除部分过期的数据。redis客户端redis-server通过tcp端口或socket来创建和redis-cli的连接可以修改redis.conf中的maxclients来指定最大连接数在建立连接之后socket会被设置为非阻塞模式同时创造一个struct redisClient来保存客户端的连接信息。1 struct redisClient {2 redisDb *db;//记录客户端当前正在使用的数据库上文提到之前有16个们默认的数据库可以通过select进行切换数据库3 int fd;//客户端正在使用的套接字描述符-1表示伪客户端(AOF文件或者Lua脚本)大于-1表示普通客户端4 robj *name;//客户端名字5 int flags;//客户端标志记录了客户端的角色以及客户端目前所处的状态6 sds querybuf;//输入缓冲区根据输入内容动态地缩小或扩大但不能超过1GB否则服务器将关闭这个客户端7 robj **argv;//命令与命令参数数组每个元素都是一个字符串对象argv[0]为命令其余元素为参数8 int argc;//argv数组的长度9 struct redisCommand *cmd;//当前执行的命令的实现函数指向命令表中的命令结构10 char buf[REDIS_REPLY_CHUNK_BYTES];//固定大小输出缓冲区数组默认大小为16KB11 int bufpos;//buf数组目前已使用的字节数量12 list *reply;//可变大小输出缓冲区链表13 obuf_soft_limit_reached_time记录了“reply”输出缓冲区第一次到达软性限制的时间用于计算持续超出软性限制的时长以此决定是否关闭客户端14 int authenticated;//0表示未通过身份验证1表示已通过身份验证15 time_t ctime创建客户端的时间可用于计算客户端与服务器连接的时间长度16 time_t lastinteraction客户端与服务器最后一次进行互动的时间可用于客户端的空转时长17 multiState mstate;//事务状态包含一个事务队列以及一个已入列命令计数器18 };db是一个指针指向Redis服务器状态结构中的“db”数组其中一个元素表示当前客户端正在使用的数据库。默认情况下Redis客户端的目标数据库为0号数据库可以通过select命令切换所以select命令的实现原理为修改redisClient.db指针让它指向服务器中指定的数据库。fd连接当前客户端与Redis服务器的套接字描述符。值为-1表示伪客户端(AOF文件或者Lua脚本)值大于-1则表示普通客户端。Redis客户端分为普通客户端与伪客户端两种类型其中通过网络连接与Redis服务器进行连接的就是普通客户端反之则是伪客户端了。伪客户端也有两种类型分别是Lua脚本的伪客户端和AOF文件的伪客户端。Redis服务器状态结构的“lua_client”属性就保存了Lua脚本的伪客户端它会在Redis服务器初始化时就被创建负责执行Lua脚本中包含的Redis命令在服务器运行的整个生命周期一直存在直至服务器关闭才会关闭。而AOF伪客户端则是在载入AOF文件时被创建用于执行AOF文件中的Redis命令在AOF文件载入完成之后被关闭。client list列出目前所有连接到服务器的普通客户端。redis的持久化AOF、RDB指的是redis持久化策略可以通过redis.conf中的参数来配置。appendfsync (always/everysec/no)save [time(s)] [times]AOF指的是保存操作命令他会将每一次redis的数据操作命令追加到文件中当键过期的时候会加入del命令并且每过一段时间会对已经生成的文件优化一次主要指的是操作命令的合并。RDB指的是执行save或bgsave命令创建一个新的RDB文件新建一个子进程把所有的数据写入文件。redis中的文件事件和时间时间redis中的事件分为文件事件和时间事件文件事件指的是通过epoll实现io多路复用程序来监听多个套接字对读、写、关闭、连接都支持事务支持原子操作。时间事件指的是redis中在默写特定时间执行操作主要有定时事件和周期性事件。所有的时间事件会被放在一个无须列表中新加入的事件会在事件的头部插入。每次执行事件的时候都会去遍历列表。正常情况下只有一个serverCron时间时间在benchmark模式下也只有两个时间事件。redis的启动过程(1)初始化服务器状态结构新创建一个struct redisServer类型的实例变量作为服务器的状态记录着整个服务器的状态并为结构中的各个属性设置默认值例如服务器的运行ID、默认配置文件路径、默认端口等等同时创建Redis命令表。(2)载入配置选项载入用户指定的配置参数和配置文件并根据用户设定的配置对服务器状态变量的相关属性进行修改。(3)初始化服务器数据结构这一步主要是为服务器状态中的一些数据结构分配内存例如“clients“链表保存所有与服务器连接的客户端的状态结构。”db“字典保存服务器的所有数据库。”lua“用于执行Lua脚本的Lua环境。”slowlog“用于保存慢查询日志。除此之外还会进行一些非常重要的设置操作例如为服务器设置进程信号处理器。创建共享对象例如经常经常用到的“OK”回复字符串对象1到10000的字符串对象等等。为serverCron函数创建时间事件。如果AOF持久化功能已经打开则打开现有的AOF文件若AOF文件不存在则创建并打开一个新的AOF文件为AOF写入做好准备。初始化服务器的后台I/O模块为将来的I/O操作做好准备。(4)还原数据库状态若服务器启用了AOF持久化功能则载入AOF文件否则载入RDB文件根据AOF文件或RDB文件记录的内容还原数据库状态同时在日志文件中打印出载入文件并还原数据库状态所耗费的时长。(5)执行事件循环一切准备就绪开始执行服务器的事件循环开始接受客户端的连接请求处理客户端发送的命令请求。来源oschina链接https://my.oschina.net/u/4332949/blog/3449911