redis get实际开销的理解水平,就代表了你的内功的深度

0 438
索鸟 2020-12-01
需要:0索币
我问大家一个问题,下图中一个最简单的例子,会导致哪些CPU开销产生?你是否能够说清楚?
<?php    ...    $redis->get('test');    ...

这个例子一下子就把大家在我的文章里学到的东西和你的实际工作结合起来了。怎么样,是不是足够简单?就是一句php代码从redis实例中获取一个key的value值而已,相信类似的代码你天天都在写。对这句redis get实际开销的理解水平,就代表了你的内功的深度。

在前面的文章中介绍了一些和CPU相关的硬件、内核知识,把开销大户进程上下文切换、系统调用、软中断的具体开销都挨个分析了一遍。没有看过的同学请关注并翻看我以前的文章。不过,这时候我觉得有很多开发同学都有一个疑惑,仍然是觉得:“我是应用层的开发,这么底层的开销和我有什么关系?” 或者是说:“线上服务器的运维不都应该是运维的工作吗?和开发又没关系”

我想说的是,如果你只是一个初级或者中级开发工程师,这些确实没有必要了解。但是如果你想成为一名高级、或者是资深开发工程师,那么你应该具备大致估算你手下写出的每一行代码开销的能力,要对自己代码在线上的运行开销负责!

1
测试准备

接下来,我们就来带大家从更深层次的方向认识到这句简单代码的开销。为了便于测试,我们对代码进行一些简单的改造,最终的实际测试文件如下(可能需要左右滑动查看)。

<?php$redis = new Redis();$redis->connect('10.153.55.119', 6339);sleep(60);echo "Test begin\n";for($i=0; $i<10000; $i++){    $redis->get('test');}echo "Test end!\n ";sleep(60);

例子非常的简单,就是一句后端同学代码里经常出现的从Redis里获取了一条数据而已。那么让我们看看它到底会产生哪些开销?

2
系统调用开销

我们使用strace命令来查看(可能需要左右滑动查看)。

# strace -c php main.php% time     seconds  usecs/call     calls    errors syscall------ ----------- ----------- --------- --------- ----------------97.24    0.039698           1     30003           poll2.20    0.000899           0     10003           sendto0.30    0.000122           0     10000           recvfrom0.13    0.000053           0     10069           gettimeofday0.03    0.000013           2         6           socket0.03    0.000012           0       408           munmap0.02    0.000008           0       657           read

我们代码所调用的get函数,其实是php的一个redis扩展提供的。该扩展又会去调用Linux系统的网络库函数,库函数再去调用内核提供的系统调用。这个调用层次模型如下:


从实际测试结果可见,每次get操作都需要执行多次系统调用才可完成。

3
进程上下文切换开销

每次次调用get后,如果数据没有返回。进程都是阻塞掉的,因此还会导致进程进入主动上下文切换。我们用实验的方式来查看一下:

# php main.php

然后再另起一个控制台,分别赶在实验开始前和实验开始后执行如下两行命令:

# grep ctxt /proc/14862/statusvoluntary_ctxt_switches:        4nonvoluntary_ctxt_switches:     43# grep ctxt /proc/14862/statusvoluntary_ctxt_switches:        10005nonvoluntary_ctxt_switches:     49

每次get都会导致进程进入自愿上下文切换,在网络IO密集型的应用里自愿上下文切换要比时间片到了被动切换要多的多!

4
软中断开销

每次在redis服务器返回数据的时候,网卡都会通过软中断的方式来让内核处理数据包。因此我们查看软中断次数(可能需要左右滑动查看)

# cat /proc/softirqsCPU0       CPU1       CPU2       CPU3HI:          0          0          0          0TIMER:  196173081  145428444  154228333  163317242NET_TX:          0          0          0          0NET_RX:  178159928     116073      10108     160712
# cat /proc/softirqsCPU0       CPU1       CPU2       CPU3HI:          0          0          0          0TIMER:  196173688  145428634  154228610  163317624NET_TX:          0          0          0          0NET_RX:  178170212     116073      10108     160712

该虚机的软中断亲和性在CPU0上,178170212-178159928 = 10284(多出来的284是机器上其它的小服务)。每次get请求收到数据返回的时候,内核必须要支出一次软中断的开销!

5
总结

看似一次非常简单的redis get操作就会把所有系统态的高开销操作都涉及到了。一次进程上下文切换、一次软中断、若干次系统调用。在经过了前面多篇文章的历练,相信大家对它们的开销有了一个量化的拿捏。其实除了上面这些容易评估到的开销外,还有如L1、L2 cache miss,以及TLB cache miss这些在进程被切换掉都会造成cache命中率下降,也会导致额外开销。

所以,你以为的简单,其实不一定简单

原文地址:https://mp.weixin.qq.com/s/buJ6BcCpBgZ7BNGaiMMsgQ

回帖
  • 消灭零回复
相关主题
2020年最新最新Kubernetes视频教程(K8s)教程 2
程序员转型之制作网课变现,月入过万告别996 1
索鸟快传2.0发布啦 1
两个不同网络的电脑怎么实现文件的互相访问呢? 1
网盘多账号登录软件 1
Java实战闲云旅游项目基于vue+element-ui 1
单点登录技术解决方案基于OAuth2.0的网关鉴权RSA算法生成令牌 1
QT5获取剪贴板上文本信息QT设置剪贴板内容 1
springboot2实战在线购物系统电商系统 1
python web实战之爱家租房项目 1
windows COM实用入门教程 1
C++游戏开发之C++实现的水果忍者游戏 1
计算机视觉库opencv教程 1
node.js实战图书管理系统express框架实现 1
C++实战教程之远程桌面远程控制实战 1
相关主题
PHP7报A non well formed numeric value encountered 0
Linux系统下关闭mongodb的几种命令分享 0
mongodb删除数据、删除集合、删除数据库的命令 0
Git&Github极速入门与攻坚实战课程 0
python爬虫教程使用Django和scrapy实现 0
libnetsnmpmibs.so.31: cannot open shared object file 0
数据结构和算法视频教程 0
redis的hash结构怎么删除数据呢? 0
C++和LUA解析器的数据交互实战视频 0
mongodb errmsg" : "too many users are authenticated 0
C++基础入门视频教程 0
用30个小时精通C++视频教程可能吗? 0
C++分布式多线程游戏服务器开发视频教程socket tcp boost库 0
C++培训教程就业班教程 0
layui的util工具格式时间戳为字符串 0
C++实战教程之远程桌面远程控制实战 1
网络安全培训视频教程 0
LINUX_C++软件工程师视频教程高级项目实战 0
C++高级数据结构与算法视频教程 0
跨域问题很头疼?通过配置nginx轻松解决ajax跨域问题 0