日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Redis源碼剖析從源碼到對(duì)照表(redis源碼對(duì)照表)

Redis源碼剖析:從源碼到對(duì)照表

在湘潭等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶(hù)提供成都網(wǎng)站建設(shè)、網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站設(shè)計(jì),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),成都全網(wǎng)營(yíng)銷(xiāo)推廣,成都外貿(mào)網(wǎng)站制作,湘潭網(wǎng)站建設(shè)費(fèi)用合理。

Redis是一個(gè)開(kāi)源的、高性能的、支持多種數(shù)據(jù)結(jié)構(gòu)的NoSQL數(shù)據(jù)庫(kù),它是由Salvatore Sanfilippo開(kāi)發(fā)的,C語(yǔ)言編寫(xiě)。Redis在工業(yè)界得到了廣泛的應(yīng)用,被譽(yù)為高性能的“鍵值存儲(chǔ)器”或“鍵值數(shù)據(jù)庫(kù)”。

由于Redis的應(yīng)用廣泛,源碼的閱讀也變得重要,本文將從源碼的角度,剖析Redis數(shù)據(jù)庫(kù)的內(nèi)部原理,幫助讀者更好地了解Redis的工作過(guò)程,并提供對(duì)照表以加深記憶。

Redis源碼剖析

Redis數(shù)據(jù)庫(kù)的源碼主要由以下幾部分組成:網(wǎng)絡(luò)、多線程、內(nèi)存分配、持久化、訂閱和發(fā)布、客戶(hù)端等。下面通過(guò)一些核心源碼的分析,讓讀者了解Redis數(shù)據(jù)庫(kù)內(nèi)部結(jié)構(gòu)。

網(wǎng)絡(luò)

Redis是基于Socket通信的,Socket通信分為分叉處理和非分叉處理兩種方式,其中非分叉處理的效率更好,且可靠性更高。

以下是Redis網(wǎng)絡(luò)連接的核心代碼:

/* Set the socket non-blocking. We have to do the same in Redis, but since
* socket operations are serialized on the event loop, it's better to
* set the socket in non-blocking mode in the accept() call, to get
* better performance inside the event loop itself. */
anetNonBlock(NULL, connfd);
/* Set TCP keep alive option to detect dead peers. */
anetKeepAlive(NULL, connfd, server.tcpkeepalive);
/* Create a client that is by default not yet registered in an event loop. */
c = createClient(connfd);
/* Check if the user is authenticated. */
if (server.requirepass) {
c->flags |= CLIENT_PENDING_WRITE;
c->auth_callback = connCreateAuthCallback(connfd, conn);
aeCreateFileEvent(server.el, connfd, AE_WRITABLE, sendAuthReply, c);
return c;
}

在上面的代碼中,anetNonBlock()函數(shù)設(shè)置連接的套接字為非阻塞模式,并且anetKeepAlive()函數(shù)設(shè)置TCP長(zhǎng)連接和心跳機(jī)制。如果需要密碼認(rèn)證,Redis數(shù)據(jù)庫(kù)會(huì)將連接添加到Redis事件服務(wù)器,等待認(rèn)證消息到達(dá)。

多線程

Redis數(shù)據(jù)庫(kù)中,多線程主要用于實(shí)現(xiàn)數(shù)據(jù)的并發(fā)讀寫(xiě)操作,并提高數(shù)據(jù)庫(kù)的并發(fā)性能。Redis使用了一種簡(jiǎn)單的多線程架構(gòu),并使用了讀寫(xiě)鎖來(lái)確保數(shù)據(jù)的安全性。

以下是Redis數(shù)據(jù)庫(kù)的多線程鎖保證代碼:

/* Acquire the lock for the specified object. This function is used in
* blocking operations, and has a timeout. */
int lockThreadedIO(const char *func, robj *key, long long timeout, aeEventLoop *el) {
connection *conn = el->ioconn;

/* Don't wt to a negative timeout. */
if (timeout
/* Create the lock key as a string object. */
robj *lockkey = createObject(OBJ_STRING,
sdscatprintf(sdsempty(), "threaded-io-lock:%s:%s",
func, (char*)key->ptr));
/* Lock the lock. */
while (timeout >= 0) {
/* Try to create the lock key with a timeout. */
long long start = ustime();
int64_t res = setnxOne(conn,lockkey,shared.cone,NULL);

/* Check if we acquired the lock. */
if (res == 1) {
decrRefCount(lockkey);
return 0;
}

/* Wt for a little bit, then try agn. */
if (timeout > THREAD_IDELTIME_CAP) {
uint64_t delay = (rand()%1000)*1000 + 500000; /* Max 1.5 sec */
delay = (delay * timeout) / THREAD_IDELTIME_CAP;
if (delay
if (delay > timeout) delay = timeout;
usleep(delay);
timeout -= (ustime()-start)/1000;
} else {
usleep(THREAD_MIN_SLEEP);
timeout -= THREAD_MIN_SLEEP/1000;
}
/* Check for SIGTERM or SIGINT signals. */
stopThreadedIOIfNeeded();
}

decrRefCount(lockkey);
errno = ETIMEDOUT;
return -1;
}

這段代碼使用了讀寫(xiě)鎖,確保線程之間的數(shù)據(jù)安全。對(duì)于讀取操作,線程可以使用共享讀鎖,允許多個(gè)線程同時(shí)訪問(wèn)相同的數(shù)據(jù)。但對(duì)于寫(xiě)操作,線程必須使用獨(dú)占寫(xiě)鎖,以確保線程之間不會(huì)干擾數(shù)據(jù)的修改。

內(nèi)存分配

Redis數(shù)據(jù)庫(kù)的內(nèi)存管理策略采用了基于Unix機(jī)制的內(nèi)存分配,包括mmap、sbrk以及malloc等。

以下是Redis內(nèi)存分配策略代碼:

/* Macro to revert back a couple of lines of code when a malloc() fls, to
* repeat the operation with a smaller request. */
#define REDIS_MALLOC_FL_CLEAN(ptr,size) do { \
zfree(ptr); \
ptr = zmalloc(size); \
if (!ptr) oom("malloc()",size); \
} while(0);
/* Allocate or realloc 'oldptr' so that it can contn at least
* 'minsize' bytes of data. */
void *zrealloc(void *oldptr, size_t size) {
void *ptr = realloc(oldptr,size);
if (!ptr) oom("realloc()",size);
return ptr;
}

/* Allocate 'size' bytes of memory, and return a pointer to the allocated
* memory. */
void *zmalloc(size_t size) {
void *ptr = malloc(size+PREFIX_SIZE);
/* Even on flure to allocate we set the prefix in order to get predictable
* behavior from zfree. */
if (!ptr) oom("malloc()",size);
*((size_t*)ptr) = size;
return (char*)ptr+PREFIX_SIZE;
}

在這段代碼中,Redis的內(nèi)存分配策略主要是通過(guò)宏定義完成,使用zmalloc()為Redis分配內(nèi)存,并設(shè)置前綴以確保內(nèi)存分配的可預(yù)測(cè)性。同時(shí),Redis代碼中還包括了內(nèi)存溢出的處理代碼,確保Redis在分配內(nèi)存時(shí)不會(huì)因?yàn)閮?nèi)存溢出而崩潰。

持久化

Redis數(shù)據(jù)庫(kù)支持?jǐn)?shù)據(jù)持久化,可以將數(shù)據(jù)保存在磁盤(pán)中,以防止宕機(jī)和數(shù)據(jù)丟失。Redis的數(shù)據(jù)持久化主要分為rdb持久化和aof持久化兩種方式。

以下是Redis數(shù)據(jù)庫(kù)的rdb持久化代碼:

/* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success. */
int rdbSave(char *filename) {
atomicSet(server.rdb_child_pid,-1);
if ((server.bgrewritechildpid != -1 || server.aof_child_pid != -1 ||
server.pipe_conns != NULL) &&
server.rdb_child_pid == -1)
{
errno = EAGN;
return REDIS_ERR;
}

int fd;
ssize_t nwritten;
FILE *fp;

/* Open the output file. */
if ((fp = fopen(filename,"w")) == NULL) {
redisLog(REDIS_WARNING,"Fled opening .rdb for saving: %s", strerror(errno));
return REDIS_ERR;
}
fd = fileno(fp);
if (server.rdb_compression) {
if (setCompressionAlgorithm(fd)
fclose(fp);
return REDIS_ERR;
}
}
/* BgSave */
beforeRDBSave();
if (rdbSaveRio(fd,&server.rdb_save Rio) == -1) {
fclose(fp);
return REDIS_ERR;
}
afterRDBSave();

fflush(fp);
if (ferror(fp)) {
fclose(fp);
return REDIS_ERR;
}
nwritten = server.rdb_save Rio .processedBytes();
if (server.rdb_checksum) {
unsigned char digest[10];
memset(digest,0,sizeof(digest));

/* Note that we are just obtning the digest of the first database.
* It's not really a good way, but redis-check-rdb will spit out a
* warning to the user. */
rio cksum;
rioInitWithFlag(&cksum,RIO_CHECKSUM);
rdbSaveRio(&cksum,NULL);
/* Append the checksum to the RDB file. */
memcpy(digest,cksum.updateChecksum(NULL,0

香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開(kāi)通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)。專(zhuān)業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。


分享題目:Redis源碼剖析從源碼到對(duì)照表(redis源碼對(duì)照表)
文章出自:http://www.dlmjj.cn/article/dhscppi.html