首页 > 技术相关, 数据库 > Redis实现之虚拟存储系统(VM)实现(四)–线程式虚存(Threaded VM)交换

Redis实现之虚拟存储系统(VM)实现(四)–线程式虚存(Threaded VM)交换

2011年8月6日 sigma 发表评论 阅读评论

非阻塞虚存的几种实现选择

由于阻塞式虚存实现有各种缺点,因此,Redis实现了非阻塞式的虚存系统。实现非阻塞式虚存系统有以下几种方法:

  1. 最显然的方法,就是把整个redis做成多线程的,每个数据库操作都是自动分配到某个线程(或者fork一个新的线程),这样就不存在阻塞的问题。但是这对redis不是一个好的解决方案,因为为了实现提高操作速度,redis没有锁,保证原子性是通过顺序执行来保证的,因此整个redis引入多线程要增加锁,导致速度变慢(也许多核上能快点),并且极大增加代码量(现在redis只有1万行代码)。
  2. 通过非阻塞式IO实现,由于redis是基于事件循环的(event-loop based),可以采用非阻塞IO。但redis的作者基于以下两点把这个否了:①非阻塞文件操作不像sockets,会导致很多不兼容的问题,这和操作系统紧密相关,要做很多和操作系统相关的工作。②另外一个原因就是,在虚存中,文件IO操作仅仅是一部分,还有很多事件花在数据的编解码上面(编解码成交换文件swap file)。
  3. 于是就剩下最后一种方法,通过增加IO线程来完成数据交换。

下面,具体介绍第三种实现,即IO线程:

IO线程

IO线程的设计目标依重要性排列如下:

  • 实现简单:尽量减少数据冲突(race)的可能性;用简单的锁;VM的代码要能够和Redis的其他代码分离(个人感觉这符合设计正交性原则)。
  • 高性能,对于客户端访问数据不会造成锁(等待)。
  • IO线程要能够编解码交换文件(针对第二种实现的缺点2)。

鉴于以上目标,Redis 的非阻塞VM实现的方式为,实现了一个redis主线程(实际和客户端交互的线程,处理请求),以及一些通过一个简单的信号量(mutex)和任务队列进行通信的IO进程。简单的说,主线程将IO请求交给IO线程进行后台处理(通过将一个(IO)任务结构交给server.io_newjobs队列)。假如没有IO进程,则新建一个。有些IO进程完成IO任务后,结果将发送到server.io_processed队列。IO进程将通过UNIX管道给主进程一个信号,以便告知已经完成,可以继续新的任务。

iojob的数据结构如下:

 typedef struct iojob {
    int type;   /* Request type, REDIS_IOJOB_* */
    redisDb *db;/* Redis database */
    robj *key;  /* This I/O request is about swapping this key */
    robj *val;  /* the value to swap for REDIS_IOREQ_*_SWAP, otherwise this
                 * field is populated by the I/O thread for REDIS_IOREQ_LOAD. */
    off_t page; /* Swap page where to read/write the object */
    off_t pages; /* Swap pages needed to save object. PREPARE_SWAP return val */
    int canceled; /* True if this command was canceled by blocking side of VM */
    pthread_t thread; /* ID of the thread processing this entry */
} iojob;
 

IO进程仅仅能处理三种类型的任务(通过上面的type域定义):

  • REDIS_IOJOB_LOAD:将给定key的对象从交换空间load回主存。
  • REDIS_IOJOB_PREPARE_SWAP:计算将val指向的对象交换到交换空间所需要的页数,计算的结果放在page域。
  • REDIS_IOJOB_DO_SWAP:将val指向的对象交换到交换空间。

主线程除了以上三项工作不做以外,其他的工作都是主线程完成的,比如通过算法找到需要交换出去的对象之类的。

本文作者: Sigma    在新浪微博关注SigmaSigmaWeibo    RSS订阅本博客
本文链接: http://www.sigma.me/2011/08/06/redis-vm-implement-threaded-vm.html
本博客采用知识共享署名—非商业性-禁止演绎使用3.0协议进行许可,转载请保留作者和原文链接。

  1. 2011年8月6日16:55 | #1

    @grapeot

    大家都能看懂的,大众的,肯定很多人写,权重就低了,哥现在主要还是要靠搜索引擎,权重很重要

    只要我写过的,都得排前面才行,否则就白写了

    (其实sigma很多人搜,我排名也比较前,但是没转化成流量,主要搜索出来的结果都是我这个博客的介绍,而不是介绍sigma这个词的文章)

  2. 2011年8月6日16:44 | #2

    牛逼。。。4了。。。

    我的意思不是生活类,而是大家都能看得懂或者受众面广的东西。这个redis的原理是不是太专业了?

  3. 2011年8月6日17:55 | #3

    有道理,如何选一个大家感兴趣但能写(或者能写得好看)的人又不多的领域就是学问了。这就是重要的东西。

  4. 2011年8月6日16:47 | #4

    查了一下哥的才2。。。主要的确没多少人链过去。。。

  5. 2011年8月6日16:06 | #5

    @grapeot

    哈哈,肯定是百度更懂中国人,知道你的喜好~

    话说google pagerank就和你博客的主题有关,要是大杂烩,pr值很低,并且google adsense匹配也不好,容易封号

    现在我在这个博客基本不写生活类等不关痛痒的东西,否则好不容易搞来的订阅量又下去了(之前经常出现我没发一篇文章,订阅量瞬间降了几个,之后又慢慢升上来,现在基本不会了)

    小炫耀一下,我的这个博客pr值已经是4是4是4啦

  6. 2011年8月6日17:58 | #6

    @grapeot

    嗯,感觉很多时候只能挖小的,之后慢慢积累,豆瓣就是这样发起来的

  7. 2011年8月6日15:54 | #7

    为毛你推荐的广告是“第二代 让男人省事,让女人不省人事”。。。

    感觉有必要把技术类blog和生活/评论类blog分开,这样有利于提高流量。至少要分到不同的tags下,方便分别订阅。

  1. 本文目前尚无任何 trackbacks 和 pingbacks.

无觅相关文章插件,快速提升流量