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

深入剖析nginx时间缓存

www.ft12.com8年前 (2017-08-08)短网址资讯2093

本文适合对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

分享给朋友:

相关文章

信息流广告崛起自媒体时代互联网营销新玩法层出不穷

信息流广告崛起自媒体时代互联网营销新玩法层出不穷

目前,信息流广告已经覆盖绝大多数网民朋友,信息流广告基本是基于移动互联网终端的,最简单直观地信息流广告出现在各大门户网站的移动APP中,如腾讯新闻、天天快报、今日头条、百度新闻、网易新闻、搜狐新闻、一点资讯等等移动资讯APP。根据国内知名数...

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

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

道德沦丧!中国电商平台被爆集体造假,造假者月入10万…

道德沦丧!中国电商平台被爆集体造假,造假者月入10万…

 近几年网购发展迅速,人们可以足不出户,就可以享受到其他国家优质的产品。然而,那些某些电商网站上大量所谓的“境外购”、“海外购”,真的是从国外买到的产品吗?近日,《新京报》曝光了一桩惊天海淘平台造假大案,国内所有大型海淘平台,几乎...

人性营销:水果店用微信轻松实现创富

人性营销:水果店用微信轻松实现创富

在松松博客投稿的第一个案例(烟油),是我们实打实做出来的。我也一直有关注近百条评论,大部分网友还是很认可,也有几位有一些怀疑。怀疑是正常的,原因在于我本人并没有把细节和原理讲透彻。那么我今天再给大家分享一个案例:我们小区的水果店是怎么用一年...

美国石油公司刚来中国卖低价油,就被发改委逼着涨回去?

美国石油公司刚来中国卖低价油,就被发改委逼着涨回去?

今天,中国网络上有消息称,已经进入中国成品油市场的美国石油公司“海湾石油”,因为其首个国内加油站的油价大大低于中国超级国企中石油和中石化的价格,竟遭到发改委等监管部门联合执法,导致其良心油价最终不得不与“两桶油”接轨。 对此,FT...

使用短网址做营销推广并不会营销网站的SEO效果

咱们在开展SEO活动时,常常需求在职业网站,职业论坛,交际网站等发布内容,并且许多时分会在文字内容中包含需求推行引流的网址。例如咱们在做YouTube视频推行时,会在上载视频时,在描绘中包含要推行引流的亚马逊网址或许网站网址。在做论坛帖子推...

发表评论

访客

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