Redis源码解析3
Everything is Object 数据结构 在Redis中,用 robj 结构表示一切数据对象,可以把它看作一种元数据(MetaData) 各种不同的结构化数据,通过该对象进行封装、传递、变换、编码,而该对象本身却十分简单 其类型定义如下: 1 typedef struct redisObject { un
Everything is Object
数据结构
在Redis中,用 robj 结构表示一切数据对象,可以把它看作一种元数据(MetaData)
各种不同的结构化数据,通过该对象进行封装、传递、变换、编码,而该对象本身却十分简单
其类型定义如下:
1 typedef struct redisObject { unsigned storage:unsigned encoding:unsigned lru:refcount; } robj;
type字段表示数据类型,有以下几种定义:
REDIS_STRING // 字符串
REDIS_LIST // 链表
REDIS_SET // 集合
REDIS_ZSET // 有序集合
REDIS_HASH // HASH结构(注意,此处不同于传统意义上的哈希表(如stl::hash_map),这里的hash仅有字段散列的语义)
REDIS_VMPOINTER // VM指针(表示数据处于VM管理之下)
encoding字段表示数据编码方式,有以下几种定义:
REDIS_ENCODING_RAW // 原始编码,就是一个原始字符串
REDIS_ENCODING_INT // INT型编码,会将数字类型的字符串编码成该格式
REDIS_ENCODING_HT // 哈希表编码,源代码中以dict结构来管理
REDIS_ENCODING_ZIPMAP // 精简编码的hash结构,更省内存
REDIS_ENCODING_LINKEDLIST // 双向链表
REDIS_ENCODING_ZIPLIST // 精简编码的链表,更省内存
REDIS_ENCODING_INTSET // 精简编码的集合,更省内存
REDIS_ENCODING_SKIPLIST //
refcount字段是对象引用计数,每多一次引用,该计数加1;每减少一次引用,该计数减1,若减至0,则释放该对象内存
操作流程
Redis源代码中,有大量的robj指针在函数间传递
下面,以redis处理“set”命令为例,对 robj的操作进行讲解
1. 在 ProcessInlineBuffer、ProcessMultiBulkBUffer中,对命令缓存进行解析
通常是以空格为分隔符进行分离,每一个字符块都编码为一个独立的robj对象
对象存储在redisClient结构中的argc数组中,提供给后续函数使用
InlineBuffer:对应于Redis单行命令
MultiBulkBuffer:对应于多行命令
2. ProcessCommand对命令进行解析,然后进行函数分发
处理流程进入具体的命令处理函数
3. setCommand是对应于“set”命令的处理函数
该函数非常简单,网站空间,主要起到一个命令接入作用
它会对obj-val进行一次尝试性的编码转换,在本例中,会尝试将val对象转换为一个INT型的对象
转换完成后,进入内部共享函数setGenericCommand处理流程
4. setGenericCommand进行实际的“set”操作逻辑处理,即:
将kv键值对,加入到该连接对应的命名空间中(即一个dict结构)
对应于该dict结构,插入操作的具体语义由一个全局性的 dictType 进行定义:
1 dictType commandTableDictType = { NULL, NULL, dictSdsKeyCompare, dictSdsDestructor, dictRedisObjectDestructor };
根据这个操作定义,执行完比后
obj-key会复制一份原始字符串,将指针加入dict中(复制操作在dbAdd函数中实现)
obj-val直接将指针加入dict中,同时将该对象的refcount加1(加引用操作在setKey函数中实现)
5. 整个处理流程结束后,释放redisClient中的argc对象数组
在本例中,导致的结果是:
obj-key引用计数减1,最终值为0,导致对象删除
obj-val引用计数减1,最终值为1,该对象继续存在于全局key的dict表中
继续上一条“set”命令,针对更进一步的命令,对redis的对象编码转换作个初步了解
在下图中,主要注意 appendCommand中,由于该命令需要改变 obj-val对象的值,从而导致obj-val从INT编码状态解码到RAW编码状态。
解码时生成了临时对象 obj-decoded
临时对象与obj-append合并,将合并后的值赋给obj-val
引用计数 php中的变量
通过引用计数管理对象的生存期,是个好主意。通过上面两张图,也可以初步看出,redis如何通过引用计数来管理对象的生死
在很多动态类型的语言中,也有类似的做法
比如在PHP中,用以下结构表示变量:
1 struct _zval_struct { zend_uint refcount; zend_uchar type; zend_uchar is_ref; }; 7 typedef struct _zval_struct zval;
其中,value是一个 “zvalue_value” 类型的指针
zvalue_value是一个union类型的结构,将不同类型的数据整合进了同一个结构里
1 typedef union _zvalue_value { dval; { 5 char *val; 6 int len; HashTable *ht; zend_object_value obj; } zvalue_value;
可以看到,PHP中的变量有两种引用计数
1. refcount:直接引用计数,赋值时计数增加
2. is_ref:间接引用计数,赋引用时计数增加
之所以有这两个值,是因为PHP中的变量有引用的概念,香港虚拟主机,并且涉及到几个重要原则:
1. 赋值零拷贝:变量赋值时,不会复制一份新的变量,而是直接对zval结构加引用,且引用计数加在refcount变量上
但是,自定义类对象的赋值,和普通变量不同,默认是赋引用,导致计数加在is_ref上
我认为这是PHP语言设计上很混乱的一个地方
2. 写时复制:变量改变会引发变量分离,导致复制一份新变量

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Redis cluster mode deploys Redis instances to multiple servers through sharding, improving scalability and availability. The construction steps are as follows: Create odd Redis instances with different ports; Create 3 sentinel instances, monitor Redis instances and failover; configure sentinel configuration files, add monitoring Redis instance information and failover settings; configure Redis instance configuration files, enable cluster mode and specify the cluster information file path; create nodes.conf file, containing information of each Redis instance; start the cluster, execute the create command to create a cluster and specify the number of replicas; log in to the cluster to execute the CLUSTER INFO command to verify the cluster status; make

How to clear Redis data: Use the FLUSHALL command to clear all key values. Use the FLUSHDB command to clear the key value of the currently selected database. Use SELECT to switch databases, and then use FLUSHDB to clear multiple databases. Use the DEL command to delete a specific key. Use the redis-cli tool to clear the data.

To read a queue from Redis, you need to get the queue name, read the elements using the LPOP command, and process the empty queue. The specific steps are as follows: Get the queue name: name it with the prefix of "queue:" such as "queue:my-queue". Use the LPOP command: Eject the element from the head of the queue and return its value, such as LPOP queue:my-queue. Processing empty queues: If the queue is empty, LPOP returns nil, and you can check whether the queue exists before reading the element.

Using the Redis directive requires the following steps: Open the Redis client. Enter the command (verb key value). Provides the required parameters (varies from instruction to instruction). Press Enter to execute the command. Redis returns a response indicating the result of the operation (usually OK or -ERR).

Using Redis to lock operations requires obtaining the lock through the SETNX command, and then using the EXPIRE command to set the expiration time. The specific steps are: (1) Use the SETNX command to try to set a key-value pair; (2) Use the EXPIRE command to set the expiration time for the lock; (3) Use the DEL command to delete the lock when the lock is no longer needed.

On CentOS systems, you can limit the execution time of Lua scripts by modifying Redis configuration files or using Redis commands to prevent malicious scripts from consuming too much resources. Method 1: Modify the Redis configuration file and locate the Redis configuration file: The Redis configuration file is usually located in /etc/redis/redis.conf. Edit configuration file: Open the configuration file using a text editor (such as vi or nano): sudovi/etc/redis/redis.conf Set the Lua script execution time limit: Add or modify the following lines in the configuration file to set the maximum execution time of the Lua script (unit: milliseconds)

Use the Redis command line tool (redis-cli) to manage and operate Redis through the following steps: Connect to the server, specify the address and port. Send commands to the server using the command name and parameters. Use the HELP command to view help information for a specific command. Use the QUIT command to exit the command line tool.

There are two types of Redis data expiration strategies: periodic deletion: periodic scan to delete the expired key, which can be set through expired-time-cap-remove-count and expired-time-cap-remove-delay parameters. Lazy Deletion: Check for deletion expired keys only when keys are read or written. They can be set through lazyfree-lazy-eviction, lazyfree-lazy-expire, lazyfree-lazy-user-del parameters.
