Redis的模块化开发设计的还是相当不错的,在Bio.h和Bio.c文件中定义了一个多线程的文件任务处理模块,在添加和处理任务的时候使用互斥锁和条件变量进行的同步,而且本身也支持多线程,这个模块的支持两个类型,一个是关闭文件,另一个是将内存中的数据刷新到磁盘中去,也算是数据持久化的一部分了。其中三个宏定义了这些数据。

#define REDIS_BIO_CLOSE_FILE    0 /*关闭一个系统调用*/
#define REDIS_BIO_AOF_FSYNC 1 /*文件数据刷新到磁盘*/
#define REDIS_BIO_NUM_OPS 2/*支持任务类型数*/

模块的基础变量数据:

static pthread_t bio_threads[REDIS_BIO_NUM_OPS];/*多线程情况下线程的个数*/
static pthread_mutex_t bio_mutex[REDIS_BIO_NUM_OPS];/*互斥锁*/
static pthread_cond_t bio_condvar[REDIS_BIO_NUM_OPS];/*条件变量*/
static list *bio_jobs[REDIS_BIO_NUM_OPS];/*后台任务链表,每个线程一个,根据下标区分*/
static unsigned long long bio_pending[REDIS_BIO_NUM_OPS];/*记录每个线程剩余的任务数*/
struct bio_job
{/*后台IO节点,任务是通过链表来维护的,这个算是链表内的节点数据,第一个是创建时间,第二个是指定参数。*/
time_t time; /* Time at which the job was created. */
/* Job specific arguments pointers. If we need to pass more than three
* arguments we can just pass a pointer to a structure or alike. */
void *arg1, *arg2, *arg3;
};

具体的实现接口,注意,这个模块中.h和.c文件中定义的接口不一样,不知道是写错了还是怎么回事,.h中定义的部分接口没有实现:

void bioInit(void); /初始化变量数据和线程数据/
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3);/*添加一个任务*/void *bioProcessBackgroundJobs(void *arg);/*处理指定的任务数组*/
unsigned long long bioPendingJobsOfType(int type);/*获取剩余的任务数*/
void bioKillThreads(void);/*关闭线程*/
1.void bioInit(void);
void bioInit(void)
{
pthread_attr_t attr;
pthread_t thread;
size_t stacksize;
int j; /*初始化条件变量和互斥锁*/
for (j = ; j < REDIS_BIO_NUM_OPS; j++)
{
pthread_mutex_init(&bio_mutex[j],NULL);
pthread_cond_init(&bio_condvar[j],NULL);
bio_jobs[j] = listCreate();
bio_pending[j] = ;
} /*初始化线程属性,自动增加线程栈的大小*/
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr,&stacksize);
if (!stacksize) stacksize = ; /* The world is full of Solaris Fixes */
while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= ;
pthread_attr_setstacksize(&attr, stacksize); /* Ready to spawn our threads. We use the single argument the thread
* function accepts in order to pass the job ID the thread is
* responsible of. */
for (j = ; j < REDIS_BIO_NUM_OPS; j++)
{
void *arg = (void*)(unsigned long) j;
if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != )
{
redisLog(REDIS_WARNING,"Fatal: Can't initialize Background Jobs.");
exit();
}
bio_threads[j] = thread;
}
}//这个没啥可说的,无非是初始化同步的数据和线程数据
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3);/*添加一个任务*/
 /*创建一个后台任务,创建任务支持多线程
添加事件和处理事件就像是消费者和生产者的问题一样,采用互斥和条件变量来控制
参数1是添加到哪个队列中,剩余是三个参数*/
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3)
{
struct bio_job *job = zmalloc(sizeof(*job)); job->time = time(NULL);
job->arg1 = arg1;
job->arg2 = arg2;
job->arg3 = arg3;
/*添加的时候要注意并发问题,添加完了发个信号*/
pthread_mutex_lock(&bio_mutex[type]);
listAddNodeTail(bio_jobs[type],job);
bio_pending[type]++;
pthread_cond_signal(&bio_condvar[type]);
pthread_mutex_unlock(&bio_mutex[type]);
}
void *bioProcessBackgroundJobs(void *arg);
/*事件消费函数*/
void *bioProcessBackgroundJobs(void *arg)
{
struct bio_job *job;
unsigned long type = (unsigned long) arg;
sigset_t sigset; /* Make the thread killable at any time, so that bioKillThreads()
* can work reliably. */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);/*设置线程为收到cancle信号马上退出*/
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock(&bio_mutex[type]);
/* Block SIGALRM so we are sure that only the main thread will
* receive the watchdog signal. */
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
redisLog(REDIS_WARNING,
"Warning: can't mask SIGALRM in bio.c thread: %s", strerror(errno)); while()
{
listNode *ln; /* The loop always starts with the lock hold. */
if (listLength(bio_jobs[type]) == )
{
pthread_cond_wait(&bio_condvar[type],&bio_mutex[type]);
continue;
}
/* Pop the job from the queue. */
ln = listFirst(bio_jobs[type]);
job = ln->value;
/* It is now possible to unlock the background system as we know have
* a stand alone job structure to process.*/
pthread_mutex_unlock(&bio_mutex[type]);
     /*处理任务的时候解除互斥锁,提高效率*/
/* 区分任务类型,具体执行 */
if (type == REDIS_BIO_CLOSE_FILE)
{
close((long)job->arg1);
}
else if (type == REDIS_BIO_AOF_FSYNC)
{
aof_fsync((long)job->arg1);
}
else
{
redisPanic("Wrong job type in bioProcessBackgroundJobs().");
}
zfree(job); /* Lock again before reiterating the loop, if there are no longer
* jobs to process we'll block again in pthread_cond_wait(). */
pthread_mutex_lock(&bio_mutex[type]);/*修改公共资源的的是要加锁发,防止并发问题*/
listDelNode(bio_jobs[type],ln);/*删除节点,并减掉任务数*/
bio_pending[type]--;
}
}
void bioKillThreads(void);/*关闭线程*/
 void bioKillThreads(void)
{
int err, j; for (j = ; j < REDIS_BIO_NUM_OPS; j++)
{
if (pthread_cancel(bio_threads[j]) == ) /*给线程发送结束信号,发送成功之后等待其结束*/
{
if ((err = pthread_join(bio_threads[j],NULL)) != )
{
redisLog(REDIS_WARNING,"Bio thread for job type #%d can be joined: %s",j, strerror(err));
}
else
{
redisLog(REDIS_WARNING,"Bio thread for job type #%d terminated",j);
}
}
}
}

这个后台任务值负责关闭系统的调用和数据的持久化。

Redis 数据持久化(一)的更多相关文章

  1. Redis学习笔记(5)——Redis数据持久化

    出处http://www.cnblogs.com/xiaoxi/p/7065328.html 一.概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存 ...

  2. Redis数据持久化,安全

    一.redis数据持久化 由于redis是一个内存数据库,如果系统遇到致命问题需要关机或重启,内存中的数据就会丢失,这是生产环境所不能允许的.所以redis提供了数据持久化的能力. redis提供了两 ...

  3. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

  4. Redis 数据持久化的方案的实现

    原文:Redis 数据持久化的方案的实现 版权声明:m_nanle_xiaobudiu https://blog.csdn.net/m_nanle_xiaobudiu/article/details/ ...

  5. Redis数据持久化—RDB持久化与AOF持久化

    目录 Redis数据持久化-RDB持久化与AOF持久化 RDB持久化 RDB文件的创建 RDB文件的载入 自动间隔性保存 检查保存条件是否满足 AOF持久化 AOF持久化的实现 AOF文件的载入与数据 ...

  6. redis 数据持久化

    1.快照(snapshots) 缺省情况情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb.你可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据 ...

  7. Redis数据持久化、数据备份、数据的故障恢复

    1.redis持久化的意义----redis故障恢复 在实际的生产环境中,很可能会遇到redis突然挂掉的情况,比如redis的进程死掉了.电缆被施工队挖了(支付宝例子)等等,总之一定会遇到各种奇葩的 ...

  8. Redis数据持久化

    持久化选项 Redis提供了两种不同的持久化方法来将数据存储到硬盘里面.一种方法叫快照(snapshotting),它可以将存在于某一时刻的所有数据都写入硬盘里面.另一种方法叫只追加文件(append ...

  9. redis数据持久化(快照/日志):

    1.RDB快照的配置选项: save // 900内,有1条写入,则产生快照 save // 如果300秒内有1000次写入,则产生快照 save // 如果60秒内有10000次写入,则产生快照 ( ...

随机推荐

  1. java集合类

    1.Collection和Collections的区别? (1)Collection是一个接口,为集合对象的基本操作提供通用的接口放法. (2)Collections是一个工具类,里面包含各种对集合的 ...

  2. 一个C#的与web服务器交互的HttpClient类

    using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Net ...

  3. ProgressDialog使用总结

    以前对ProgressDialog不太熟练,特地看到的这个文章 ProgressDialog的使用  ProgressDialog 继承自AlertDialog,AlertDialog继承自Dialo ...

  4. Gunicorn 问题

    Does Gunicorn suffer from the thundering herd problem? The thundering herd problem occurs when many ...

  5. BZOJ3196——二逼平衡树

    1.题目大意:给你一个序列,有5种操作,都有什么呢... 1> 区间第k小 这个直接用二分+树套树做 2> 区间小于k的有多少 这个直接用树套树做 3> 单点修改 这个直接用树套树做 ...

  6. 我对自己提的几个关于cocos2dx的几个问题

    1.友元函数的定义: 2.运算符重载: 3.内存关机机制: 4.动作侦听: 5.单点触摸: 6.触摸目标判断: 7.事件传递: 8.多点触摸: 9.加速传感器: 10.物理按键交互: 11.绘图API ...

  7. Android的一种MVP模式框架

    今天给大家分享的是一种将view的初始化和逻辑与activity分离的架构,采用的是mvp模式.但令人遗憾的是,这仅仅是一个新的思路,我在实际使用中发现其并不能完全将UI逻辑与activity分开,所 ...

  8. 解决 QtCreator 3.5(4.0)无法输入中文的问题

    解决 QtCreator 3.5.1无法输入中文的问题 [TOC] 环境是ubuntu 15.10 ubuntu软件源中下载安装的fctix-libs-qt5现在没有用,版本太旧了. 自己下载fcti ...

  9. 如何给ZenCart网站livezilla客服系统?

    大致步骤: 1 去官网下载livezilla

  10. 【GoLang】golang context channel 详解

    代码示例: package main import ( "fmt" "time" "golang.org/x/net/context" ) ...