search
HomeDatabaseMysql Tutorialhiredis 源码学习

前段时间学习 Redis 时候,听到 hiredis 的大名,正好也在做异步的学习,就找来代码学习一下。我几乎不太会 C,仅限于最简单的语法,完全没有在生产环境中写过,所以先看个 Client 简单代码,下次看 Memcached 代码应该会更顺畅一些。 Hiredis 是用 C 写的 R

前段时间学习 Redis 时候,听到 hiredis 的大名,正好也在做异步的学习,就找来代码学习一下。 我几乎不太会 C,仅限于最简单的语法,完全没有在生产环境中写过, 所以先看个 Client 简单代码,下次看 Memcached 代码应该会更顺畅一些。

Hiredis 是用 C 写的 Redis 客户端,对 Redis 协议进行了简单的封装, 同时提供了同步和异步的两种 API。Hiredis 的代码位于 https://github.com/redis/hiredis。

一分钟使用入门

同步 API 的调用方法:

redisContext *context = redisConnect("127.0.0.1", 6379);
reply = redisCommand(context, "SET foo %s", value); 
printf("PING: %s\n", reply->str);
freeReplyObject(reply)
redisFree(context);

Redis ae 异步 API 的调用方法,使用 Redis 自己的 ae 事件库, 至于为什么 Redis 没有使用 libevent 或者 libev,可以参考 Reason, 中文翻译:

void connectCallback(const redisAsyncContext *c, int status) {
    printf("Connected...\n");
}
void disconnectCallback(const redisAsyncContext *c, int status) {
    printf("Disconnected...\n");
}
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
    redisReply *reply = r;
    if (reply == NULL) return;
    printf("argv[%s]: %s\n", (char*)privdata, reply->str);
    redisAsyncDisconnect(c);
}
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
loop = aeCreateEventLoop();
redisAeAttach(loop, c);
redisAsyncSetConnectCallback(c,connectCallback);
redisAsyncSetDisconnectCallback(c,disconnectCallback);
redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");

Libev 异步 API 调用,因为 adapters/*.h 封装的好,所以几乎和 ae 调用一致:

void connectCallback(const redisAsyncContext *c, int status) {
    printf("Connected...\n");
}
void disconnectCallback(const redisAsyncContext *c, int status) {
    printf("Disconnected...\n");
}
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
    redisReply *reply = r;
    if (reply == NULL) return;
    printf("argv[%s]: %s\n", (char*)privdata, reply->str);
    /* Disconnect after receiving the reply to GET */
    redisAsyncDisconnect(c);
}
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
redisLibevAttach(EV_DEFAULT_ c);
redisAsyncSetConnectCallback(c,connectCallback);
redisAsyncSetDisconnectCallback(c,disconnectCallback);
redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");

Hiredis 还支持使用 libevent,我就不列出来了。

详细的使用 example 可以看 https://github.com/redis/hiredis/tree/master/examples。

主要结构

  • redisReply
  • redisReader
  • redisContext

流程

同步连接

同步连接的代码在 hiredis.cnet.c 中。

redisConnect / redisConnectWithTimeout / redisConnectNonBlock 都调用了 net.c 里面的 redisContextConnectTcp。使用 fcntl(fd, F_SETFL, flags) 设置是否阻塞连接。

O_NONBLOCK 即 Socket 非阻塞模式,但仍然是同步的哦。

事实上,无论阻塞还是非阻塞,hiredis 都会使用非阻塞(poll)来 connect 连接服务器,会返回 -1,并且 errnoEINPROGRESS,这是非阻塞模式正常的表现。 为什么阻塞模式也会强制使用非阻塞的 poll 连接?其实是为了能够支持 timeout 功能。 hiredis 在连接成功之后,按照之前需求重新设定为阻塞或者非阻塞模式。

关于如何设计超时功能,可以参考 http://blog.csdn.net/ast_224/article/details/2957294。

命令

使用 va_list 解决变参问题(C 也支持变长参数,被惊呆了,我果然是 C 盲啊)。

int redisFormatCommand(char **target, const char *format, ...) {
    va_list ap;
    int len;
    va_start(ap,format);
}

redisvCommand 用来执行阻塞Redis 命令,它会调用 __redisBlockForReply, 内部调用 redisBufferWrite 从 socket 写 buffer,然后同步等待,从 redisBufferRead 读数据,用 redisGetReplyFromReader 解析返回数据。

异步连接

异步调用的代码在 async.c 中,我先看 ae 库。

重要的结构是 redisAsyncContextredisAeEvents,前者重要的方法是注册回调函数: addRead / delRead / addWrite / delWrite,后者是用来存放 loop / fd / event stream 的。

异步连接时候,仍然使用 redisContextConnectTcp 来发起到服务器的非阻塞连接。

使用 aeCreateEventLoop 创建一个事件循环,然后使用 redisAeAttachcontext 注册事件,比如说 aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e) 就注册了一个 read 事件,并将 callback 调用设置到 redisAeReadEventredisAeReadEvent 再将这个事件托管给 redisAsyncHandleRead(定义在 async.c 里面, 被三个 event 库调用)。

所以,hiredis 通过 adapter 的封装,屏蔽了 ae / libevent / libev 的 API 差异, 从而可以灵活的选择。据说 ae 是从两个 libevent 库重写过来的,可是我觉得 ae 的风格和 libev 比较像,而 libevent 的风格比较好理解。

如果拿这段代码的复杂度和 Tornado 的 IOLoop 进行对比,真实感觉 Tornado 那段 API 封装太人性化了,C 的代码写起来好复杂,系统 API、资源控制、错误控制都挺麻烦。

Redis ae 事件库的分析可以参考 http://my.oschina.net/u/917596/blog/161077#OSC_h4_6。 Libevent 的一个简单教程 http://www.wangafu.net/~nickm/libevent-book/01_intro.html。

关于 C

作为 C 渣的我,勉强读完 hiredis,感觉那点 C 基础完全不够用, 稍微将学习过程中疑惑的地方罗列一下:

  • IFDEF 使用,可以防止重复导入同一个头文件定义,这里有一个详细的解释 http://faculty.cs.niu.edu/~mcmahon/CS241/c241man/node90.html
  • __cplusplus: C++ 里面定义了这个变量,而 C 没有定义,所以当 C++ 编译器识别 source 时候,通过这个加上 ifdef 来使用 extern 编译 C 代码。
  • long long: long 只能存放 32 位,long long 可以存放 64 位长度,即 0 - 2^64-1。
  • c->flags |= REDIS_BLOCK / c->flags &= ~REDIS_BLOCK; 简洁的位操作。
  • sds(simple dynamic string)是 Redis 自己实现的 C String 字符串结构。
  • ((void)fd) 好像是将 fd 指针转成无类型的指针,不知道有什么用处。

原文链接: http://blog.log4d.com/2014/03/hiredis/
3a1ff193cee606bd1e2ea554a16353ee

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Explain the InnoDB Buffer Pool and its importance for performance.Explain the InnoDB Buffer Pool and its importance for performance.Apr 19, 2025 am 12:24 AM

InnoDBBufferPool reduces disk I/O by caching data and indexing pages, improving database performance. Its working principle includes: 1. Data reading: Read data from BufferPool; 2. Data writing: After modifying the data, write to BufferPool and refresh it to disk regularly; 3. Cache management: Use the LRU algorithm to manage cache pages; 4. Reading mechanism: Load adjacent data pages in advance. By sizing the BufferPool and using multiple instances, database performance can be optimized.

MySQL vs. Other Programming Languages: A ComparisonMySQL vs. Other Programming Languages: A ComparisonApr 19, 2025 am 12:22 AM

Compared with other programming languages, MySQL is mainly used to store and manage data, while other languages ​​such as Python, Java, and C are used for logical processing and application development. MySQL is known for its high performance, scalability and cross-platform support, suitable for data management needs, while other languages ​​have advantages in their respective fields such as data analytics, enterprise applications, and system programming.

Learning MySQL: A Step-by-Step Guide for New UsersLearning MySQL: A Step-by-Step Guide for New UsersApr 19, 2025 am 12:19 AM

MySQL is worth learning because it is a powerful open source database management system suitable for data storage, management and analysis. 1) MySQL is a relational database that uses SQL to operate data and is suitable for structured data management. 2) The SQL language is the key to interacting with MySQL and supports CRUD operations. 3) The working principle of MySQL includes client/server architecture, storage engine and query optimizer. 4) Basic usage includes creating databases and tables, and advanced usage involves joining tables using JOIN. 5) Common errors include syntax errors and permission issues, and debugging skills include checking syntax and using EXPLAIN commands. 6) Performance optimization involves the use of indexes, optimization of SQL statements and regular maintenance of databases.

MySQL: Essential Skills for Beginners to MasterMySQL: Essential Skills for Beginners to MasterApr 18, 2025 am 12:24 AM

MySQL is suitable for beginners to learn database skills. 1. Install MySQL server and client tools. 2. Understand basic SQL queries, such as SELECT. 3. Master data operations: create tables, insert, update, and delete data. 4. Learn advanced skills: subquery and window functions. 5. Debugging and optimization: Check syntax, use indexes, avoid SELECT*, and use LIMIT.

MySQL: Structured Data and Relational DatabasesMySQL: Structured Data and Relational DatabasesApr 18, 2025 am 12:22 AM

MySQL efficiently manages structured data through table structure and SQL query, and implements inter-table relationships through foreign keys. 1. Define the data format and type when creating a table. 2. Use foreign keys to establish relationships between tables. 3. Improve performance through indexing and query optimization. 4. Regularly backup and monitor databases to ensure data security and performance optimization.

MySQL: Key Features and Capabilities ExplainedMySQL: Key Features and Capabilities ExplainedApr 18, 2025 am 12:17 AM

MySQL is an open source relational database management system that is widely used in Web development. Its key features include: 1. Supports multiple storage engines, such as InnoDB and MyISAM, suitable for different scenarios; 2. Provides master-slave replication functions to facilitate load balancing and data backup; 3. Improve query efficiency through query optimization and index use.

The Purpose of SQL: Interacting with MySQL DatabasesThe Purpose of SQL: Interacting with MySQL DatabasesApr 18, 2025 am 12:12 AM

SQL is used to interact with MySQL database to realize data addition, deletion, modification, inspection and database design. 1) SQL performs data operations through SELECT, INSERT, UPDATE, DELETE statements; 2) Use CREATE, ALTER, DROP statements for database design and management; 3) Complex queries and data analysis are implemented through SQL to improve business decision-making efficiency.

MySQL for Beginners: Getting Started with Database ManagementMySQL for Beginners: Getting Started with Database ManagementApr 18, 2025 am 12:10 AM

The basic operations of MySQL include creating databases, tables, and using SQL to perform CRUD operations on data. 1. Create a database: CREATEDATABASEmy_first_db; 2. Create a table: CREATETABLEbooks(idINTAUTO_INCREMENTPRIMARYKEY, titleVARCHAR(100)NOTNULL, authorVARCHAR(100)NOTNULL, published_yearINT); 3. Insert data: INSERTINTObooks(title, author, published_year)VA

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

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

Hot Tools

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool