当前位置:首页 > 短网址资讯 > 正文内容

深入剖析nginx时间缓存

www.ft12.com7年前 (2017-08-08)短网址资讯1911

本文适合对nginx实现原理比较感兴趣的同学阅读,需要具备一定的服务端编程知识。

一、背景

在服务器开发领域,时间的准确度关系到系统能否正常运行,尤其是当系统中存在超时事件需要处理时。但是系统时间的获取需要一次昂贵的系统调用,作为一款成熟的服务器软件,Nginx是如何优化这部分的性能开销?

二、时间缓存

接触过系统设计的同学都知道,对于频繁的数据获取,在数据未变化的情形下,可以通过增加缓存来优化性能,因为缓存的访问速度远高于源数据的访问速度。这样的例子有很多,比如CPU设计有二级缓存,在传统的database基础上有了我们今天的redis、memcache等nosql。对于系统时间也一样,既然获取系统时间开销较大,可以尝试着将获取到的时间缓存起来,需要时直接从缓存中取就可以了。但与此同时,也引入了缓存时间与实际时间不一致的可能,下面看看Nginx是如何解决这一问题。

三、设计与实现

Nginx时间缓存设计

如上图所示,Nginx时间缓存包括时间读取和时间写入者,当需要更新时间时,nginx调用gettimeofday系统调用获取时间,然后更新缓存。需要获取时间的代码直接从time cache中取出即可。

这里又产生了新的问题,具体包括:

  • 读写并发,即读和写同时操作时间缓存会造成获取的时间混乱。

  • 多写并发,多个执行体同时更新时间缓存,同样造成时间混乱。

而常见的解决互斥的方案包括:

  • 加锁保证数据串行化

  • 无锁化设计

像Nginx这样对于性能有着极致追求的server来说,自然不会使用系统自带的锁机制。其实现的ngx_lock和ngx_unlock的背后都是无锁化的原子操作。

  1. 对于多写并发,nginx在ngx_time_update函数中通过全局的ngx_time_lock进行互斥,确保同一时刻只会存在一个执行体更新时间缓存。

  2. 对于读写并发,nginx设计了NGX_TIME_SLOTS个slot,用于隔离读写操作的时间缓存。同时引入时间缓存指针,原子地更新当前缓存的指向位置。

Nginx时间缓存实现

下面看具体实现代码(以nginx-1.13.1为例src/core/ngx_times.c):

void ngx_time_update(void)
{
...
//ngx_time_lock用于互斥,避免同时更新时间
    if (!ngx_trylock(&ngx_time_lock)) {
        return;
    }
//获取当前时间
    ngx_gettimeofday(&tv);
    sec = tv.tv_sec;
    msec = tv.tv_usec / 1000;
    ngx_current_msec = (ngx_msec_t) sec * 1000 + msec;
    tp = &cached_time[slot];

//秒值一致则只需要更新当前slot的msec
    if (tp->sec == sec) {
        tp->msec = msec;
        ngx_unlock(&ngx_time_lock);
        return;
    }
//获取下一slot
    if (slot == NGX_TIME_SLOTS - 1) {
        slot = 0;
    } else {
        slot++;
    }
    tp = &cached_time[slot];
    tp->sec = sec;
    tp->msec = msec;
    ngx_gmtime(sec, &gmt);
    p0 = &cached_http_time[slot][0];
    (void) ngx_sprintf(p0, "%s, %02d %s %4d %02d:%02d:%02d GMT",
                       week[gmt.ngx_tm_wday], gmt.ngx_tm_mday,
                       months[gmt.ngx_tm_mon - 1], gmt.ngx_tm_year,
                       gmt.ngx_tm_hour, gmt.ngx_tm_min, gmt.ngx_tm_sec);
    ...//类似更新ngx_cached_err_log_time.data等
    ngx_memory_barrier();

    ngx_cached_time = tp;
    ngx_cached_http_time.data = p0;
    ngx_cached_err_log_time.data = p1;
    ngx_cached_http_log_time.data = p2;
    ngx_cached_http_log_iso8601.data = p3;
    ngx_cached_syslog_time.data = p4;

    ngx_unlock(&ngx_time_lock);
}

ngx_time_update的流程图为: 

值得一提的是,这里采用了ngx_memory_barrier来避免指令重排,这样可以尽可能地保证ngx_cached_time、ngx_cached_http_time.data、ngx_cached_err_log_time.data、ngx_cached_http_log_time.data、ngx_cached_http_log_iso8601.data、ngx_cached_syslog_time.data中存储的时间数据一致。

slot设计

上面谈到了nginx采用slot来从空间上避免读写执行体同时操作时间缓存,slot的设计规则为: 

  • 获取时间的执行体采用ngx_timeofday获取了当前ngx_cached_time的快照,随后读取对应的slot中数据,包括sec和msec。

  • 更新时间的执行体通过ngx_time_update原子更新ngx_cached_time指向,这样更新之后的时间读取就是新的slot中的时间数据。

这里,nginx利用了修改指针的原子性,确保读写不会造成时间数据混乱。而时间数据本身包括sec和msec,无法完成修改的原子性,这种将非原子性修改操作转换为原子性修改操作的手法,值得借鉴。

想要获取最新技术文章?欢迎订阅微信公众号----软件编程之路

扫描二维码推送至手机访问。

版权声明:本文由短链接发布,如需转载请注明出处。

本文链接:https://www.ft12.com/article_389.html

分享给朋友:

相关文章

短网址和二维码的应用:从零开始实现一套聚合支付系统

短网址和二维码的应用:从零开始实现一套聚合支付系统

短网址和二维码在移动扫码支付领域应用越来越广泛,FT12短网址的小编出门从来不带钱,现在从吃饭、交通、购物,甚至是取款机取款,都已经不需要钱和银行卡了。那么这么流行的二维码扫码支付,是如何实现的呢?其实聚合支付的原理很简单,长网址生成短网址...

从网吧到网咖:80后男生的社交情怀

网鱼网咖的电脑区也和传统网吧大相径庭,采取类似阶梯教室的环状布局,摆放清一色的苹果一体机。除了从包房中不时传出“别送别送”(注:意思是告诫队友别送死)的叫声和激动的呼喊声,工作日时间的大厅中并没什么人,穿着印有网鱼logo白衬衫店员时不时驻...

短链接的好处与缺点

缩址,又称短址,短网址,网址延长,延长网址,网址延长等,指的是一种互联网上的技巧与办事。此办事可以或许供给一个异常短小的网址以取代本来的能够较长的网址,将长的网址位址延长。用户拜访延长后的网址时,平日将会重定向到本来的网址。大多数的网址延长...

MySQL大表删除解决方案

1. 表删除问题汇总mysql如何删除表删除大表如何优化、解决2. 删除表原理与优化删除表原理上分为2部分:buffer pool页面清除过程。在删除表的时候,Innodb 会将文件在buffer pool中对应的页面清除。对于删除表的页面...

玩王者荣耀觉得辅助都是躺赢的,祝你们对手遇到我

玩王者荣耀觉得辅助都是躺赢的,祝你们对手遇到我

我以前玩虚荣的时候,固定打游走的位置,靠着天使奥达基,经常被朋友夸。但也偶尔也被人嫌弃,我有个朋友,总认为辅助就是天生女孩子玩儿的,男人就该往前冲冲冲。他打虚荣的时候,玩豹哥扛着斧头就往前冲,每次打着打着人不见了,对兵矿有谜一样的热情,队伍...

FT12短网址:腾讯,亚洲活跃的科技公司投资者

FT12短网址:腾讯,亚洲活跃的科技公司投资者

[ FT12短网址资讯 ] 根据CB Insights最新数据表明,随着亚洲科技生态系统的发展创新,企业风险投资者在私募市场扮演着更重要的角色,腾讯是亚洲活跃的科技公司投资者。根据CB Insights最新数据表明,随着...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。