前段时间学习 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.c
和 net.c
中。
redisConnect
/ redisConnectWithTimeout
/ redisConnectNonBlock
都调用了
net.c
里面的 redisContextConnectTcp
。使用 fcntl(fd, F_SETFL, flags)
设置是否阻塞连接。
O_NONBLOCK
即 Socket 非阻塞模式,但仍然是同步的哦。
事实上,无论阻塞还是非阻塞,hiredis 都会使用非阻塞(poll)来
connect
连接服务器,会返回 -1,并且 errno
为 EINPROGRESS
,这是非阻塞模式正常的表现。
为什么阻塞模式也会强制使用非阻塞的 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 库。
重要的结构是 redisAsyncContext
和 redisAeEvents
,前者重要的方法是注册回调函数:
addRead
/ delRead
/ addWrite
/ delWrite
,后者是用来存放 loop / fd / event stream
的。
异步连接时候,仍然使用 redisContextConnectTcp
来发起到服务器的非阻塞连接。
使用 aeCreateEventLoop
创建一个事件循环,然后使用 redisAeAttach
给
context
注册事件,比如说 aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e)
就注册了一个 read
事件,并将 callback 调用设置到 redisAeReadEvent
,
redisAeReadEvent
再将这个事件托管给 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

MySQL은 초보자가 데이터베이스 기술을 배우는 데 적합합니다. 1. MySQL 서버 및 클라이언트 도구를 설치하십시오. 2. SELECT와 같은 기본 SQL 쿼리를 이해하십시오. 3. 마스터 데이터 작업 : 데이터를 만들고, 삽입, 업데이트 및 삭제합니다. 4. 고급 기술 배우기 : 하위 쿼리 및 창 함수. 5. 디버깅 및 최적화 : 구문 확인, 인덱스 사용, 선택*을 피하고 제한을 사용하십시오.

MySQL은 테이블 구조 및 SQL 쿼리를 통해 구조화 된 데이터를 효율적으로 관리하고 외래 키를 통해 테이블 간 관계를 구현합니다. 1. 테이블을 만들 때 데이터 형식을 정의하고 입력하십시오. 2. 외래 키를 사용하여 테이블 간의 관계를 설정하십시오. 3. 인덱싱 및 쿼리 최적화를 통해 성능을 향상시킵니다. 4. 데이터 보안 및 성능 최적화를 보장하기 위해 데이터베이스를 정기적으로 백업 및 모니터링합니다.

MySQL은 웹 개발에 널리 사용되는 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 주요 기능에는 다음이 포함됩니다. 1. 다른 시나리오에 적합한 InnoDB 및 MyISAM과 같은 여러 스토리지 엔진을 지원합니다. 2.로드 밸런싱 및 데이터 백업을 용이하게하기 위해 마스터 슬레이브 복제 기능을 제공합니다. 3. 쿼리 최적화 및 색인 사용을 통해 쿼리 효율성을 향상시킵니다.

SQL은 MySQL 데이터베이스와 상호 작용하여 데이터 첨가, 삭제, 수정, 검사 및 데이터베이스 설계를 실현하는 데 사용됩니다. 1) SQL은 Select, Insert, Update, Delete 문을 통해 데이터 작업을 수행합니다. 2) 데이터베이스 설계 및 관리에 대한 생성, 변경, 삭제 문을 사용하십시오. 3) 복잡한 쿼리 및 데이터 분석은 SQL을 통해 구현되어 비즈니스 의사 결정 효율성을 향상시킵니다.

MySQL의 기본 작업에는 데이터베이스, 테이블 작성 및 SQL을 사용하여 데이터에서 CRUD 작업을 수행하는 것이 포함됩니다. 1. 데이터베이스 생성 : createAbasemy_first_db; 2. 테이블 만들기 : CreateTableBooks (idintauto_incrementprimarykey, titlevarchar (100) notnull, authorvarchar (100) notnull, published_yearint); 3. 데이터 삽입 : InsertIntobooks (Title, Author, Published_year) VA

웹 응용 프로그램에서 MySQL의 주요 역할은 데이터를 저장하고 관리하는 것입니다. 1. MySQL은 사용자 정보, 제품 카탈로그, 트랜잭션 레코드 및 기타 데이터를 효율적으로 처리합니다. 2. SQL 쿼리를 통해 개발자는 데이터베이스에서 정보를 추출하여 동적 컨텐츠를 생성 할 수 있습니다. 3.mysql은 클라이언트-서버 모델을 기반으로 작동하여 허용 가능한 쿼리 속도를 보장합니다.

MySQL 데이터베이스를 구축하는 단계에는 다음이 포함됩니다. 1. 데이터베이스 및 테이블 작성, 2. 데이터 삽입 및 3. 쿼리를 수행하십시오. 먼저 CreateAbase 및 CreateTable 문을 사용하여 데이터베이스 및 테이블을 작성한 다음 InsertInto 문을 사용하여 데이터를 삽입 한 다음 최종적으로 SELECT 문을 사용하여 데이터를 쿼리하십시오.

MySQL은 사용하기 쉽고 강력하기 때문에 초보자에게 적합합니다. 1.MySQL은 관계형 데이터베이스이며 CRUD 작업에 SQL을 사용합니다. 2. 설치가 간단하고 루트 사용자 비밀번호를 구성해야합니다. 3. 삽입, 업데이트, 삭제 및 선택하여 데이터 작업을 수행하십시오. 4. Orderby, Where and Join은 복잡한 쿼리에 사용될 수 있습니다. 5. 디버깅은 구문을 확인하고 쿼리를 분석하기 위해 설명을 사용해야합니다. 6. 최적화 제안에는 인덱스 사용, 올바른 데이터 유형 선택 및 우수한 프로그래밍 습관이 포함됩니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

Eclipse용 SAP NetWeaver 서버 어댑터
Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

SublimeText3 영어 버전
권장 사항: Win 버전, 코드 프롬프트 지원!

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

Dreamweaver Mac版
시각적 웹 개발 도구
