您当前的位置:首页 > 电脑百科 > 站长技术 > 服务器

高并发的一些总结

时间:2019-11-11 13:35:50  来源:  作者:

本文转自公众号"lunewcome"。

有很多“奇技淫巧”的高并发,但基础知识的掌握程度决定了我们所写代码的并发程度,对基础足够了解才能写出并发性能更高的程序,所以本文先总结一些基础,然后再看一些具体例子。这个总结不是从头开始的详细介绍,另外影响并发性能的因素很多,想必这里说的也不是全部。

整数读写的原子性
计算机保证读写整数或指针是原子的,只要地址是按字长对齐的。要注意的是这里的原子性并不是“线程安全”什么的,而仅仅是指不会读到“乱七八糟”的值,比如有10个线程并发地往整数变量a中写0~9,那么只会读到0~9中的某个值而不会是其它任何值。

程序员视角下的缓存
总有人担心写指令是先写到缓存,经过某一段时间后再“刷”新到内存,而在这段时间内其它线程读不到最新值;还有一些文章总结了很多底层的或硬件的东西,比如“write buffer”。其实从程序员的角度看只要记住这两点:
1)利用缓存提高性能,例如避免伪共享,注意缓存行大小
2)不需要在意缓存更新问题,这是由硬件通过MESI协议保证的,我们只要记住一个线程执行完写入指令后,其它线程再从内存读时就能拿到最新值。
注意第二点,可能有人会说“既然如此,为什么多线程并发写一个整数,结果仍然是一个非确定的值”?其它第二点并不等同于线程同步操作,它只是缓存和内存之间的一致性,并不是指多线程写缓存/内存时的一致性/同步。

执行顺序与内存屏障(内存栅)
有两个地方可能“乱序执行”:一是编译器可能优化调整指令顺序,二是为了提高性能现代cpu几乎都是乱序执行(弱内存序),如powerpc和arm,常用的x86(强内存序)也不保证读写完全有序。这是不能用doube-check实现单例模式的原因。为了保证顺序性,在一些关键地方就必须加入内存屏障。屏障的作用就是当它之前的语句全部执行完后,才能执行它后面的语句。这方面也有很多比较底层的文章,但单纯从程序员的角度看,只要理解概念然后就老实用c++11提供的接口吧,原因是:
1)硬件差异大,但并不需要所有人去了解并解决。
2)c++11的封装的是各平台下能实现的最高性能,没必要自己弄一套。

伪共享
缓存失效是指整个缓存行失效,而不是其中的一部分,所以如果多个cpu/核的缓存中保存了同一缓存行,根据MESI协议,当某一个cpu/核写该缓存行时其余cpu/核上的缓存行都将失效。这个描述包含“真共享”和伪共享,当各cpu/核读写同一变量时就是“真共享”,读写不同变量时就是伪共享。“真共享”是我自己造的词,没见别人这么叫过,应该是因为它比伪共享容易察觉的多,不需要多说。伪共享的直接结果就是“cache miss”,这对性能影响很大,所以在关键数据结构上需要格外注意。只有理解了伪共享,才能知道用shard_ptr来回拷贝并非想象的那么高性能,才能知道读写锁不是描述的那么美好,等等。

下面是一些实践总结。

map
c++中的std::map,std::unordered_map都不是线程安全的,在多线程环境下需要加锁。加一把“大锁”当然安全但性能很差。一种简单有效的办法是仿效JAVA中的分段锁:定义多个map,每个都用一个mutex来保护读写。访问时首先判断key落在哪个段,再对该段的mutex加锁,然后就能安全地访问对应的map了。通过这种分段的方式的降低了冲突概率,提高了并发,简单而且性能不差。我在实际中一般用32或64个段,还没有发现有瓶颈问题。
使用原子操作实现map能得到更好的并发性能,但要自己去实现。最好先看看用原子操作实现一个list有多麻烦再决定要不要实现无锁map。

vector(可变长数组):Append-only
如何实现高并发、线程安全的vector?我实现过这样一样链表式的数组:每个数组都是等长的,写满后就申请一个新的并用指针链接到当前数组后面。这样就形成了一个“链表式的数组”,特点是顺序读写性能好但随机读性能稍差。链接用的指针需要用一个原子操作,保证申请完新数组并适当初始化后再加入到链表中。

RCU(Read,Copy Update)
RCU的概念很早就有,linux内核2.6版本实现了相应接口。它的大致思想是:Read是无锁的但要标记读的开始,写时首先Copy原内容,在拷贝上完成Update操作后替换原内容;待所有的Read都不再引用原内容后,删除原内容。
RCU的关键就在于如何知道所有的Read都不再引用原内容,2.6版本的实现思路是读时开启“禁止抢占”,这样读时就没有上下文切换,所以当写端发现所有cpu都有过一次上下文切换后,就能确定所有Read已经走出了保护区域,不再引用原内容。在更新的版本中,linux实现了分级RCU,能进一步提高并发,适应多cpu环境(成百上千个cpu的机器)。
操作系统要考虑的环境当然比应用程序复杂恶劣的多,而我们是可以用些取巧的办法的:
1)我实际中实现过这样一个双buffer:一个用于读,另一个用于写,读写切换后再等待一段时间才删除切换下来的buffer。这个双buffer能工作的关键是“这段时间”比线上请求的耗时长得多,比如1~10s,而线上请求一般在ms级完成。
2)上面的vector也可以用类似思路实现,即容量时重新申请2倍大的空间,Copy原vector的内容,再切换两个buffer的指针。这样就能有很高的随机读性能,在不触发扩容时写性能也很高(大部分情况如此)。

brpc中的dbd(Doubly-Buffered-Data)
绝妙,是我第一次见到这个神奇操作时的感受,我实在惊叹---真是想知道作者当初如何想到这样巧妙的思路。直到我了解了RCU的实现,我猜测作者可能是受了RCU的启发。和RCU类似,dbd也是适合读多写少的场景,并且也都要等待所有的读完成。dbd也是一个双buffer,和我的双buffer不同的是:
1)定义thread local的mutex,每次读buffer时先获取该锁
2)定义保证顺序写的mutex,写时先获取该锁
3)写操作切换buffer后,逐一去获取1)中所有的thread local的mutex锁,获取后立即释放。好玩的是这一步,请思考下为什么这样就能保证所有读都已经完成?
这和RCU是多么的相像!只不过一个是等待cpu一个是等待线程。
像我同事wonderfu一样,致敬brpc。

thread local
最高的并发就是完全隔离,互不影响,thread local天生如此。实际上不仅brpc的dbd,我们熟知的tcmalloc和jemalloc也都使用了thread local特性,所以让我们记住这高并发最后的利器吧。
最后,还有一项来自数据库的技术:mvcc(Multiversion Concurrency Control),我平时还没有用到,只是提一下就不细说了。

参考:
https://www.kernel.org/doc/Documentation/RCU/whatisRCU.txt
https://www.kernel.org/doc/Documentation/memory-barriers.txt
https://github.com/Apache/incubator-brpc/blob/master/docs/cn/lalb.md



Tags:高并发   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,...【详细内容】
2021-12-08  Tags: 高并发  点击:(23)  评论:(0)  加入收藏
一、幂等性概念在数学里,幂等有两种主要的定义。1、在某二元运算下,幂等元素是指被自己重复运算(或对于函数是为复合)的结果等于它自己的元素。例如,乘法下唯一两个幂等实数为0和...【详细内容】
2021-10-09  Tags: 高并发  点击:(45)  评论:(0)  加入收藏
原文链接: https://mp.weixin.qq.com/s/MTw7z6n_wk4y4CTmGkoRoA一切要从CPU说起你可能会有疑问,讲多线程为什么要从CPU说起呢?原因很简单,在这里没有那些时髦的概念,你可以更加清...【详细内容】
2021-08-13  Tags: 高并发  点击:(97)  评论:(0)  加入收藏
题目:高并发情况下,数据库该如何设计?Java高级面试题:为什么要分库分表( 设计高并发系统的时候 , 数据库层面该如何设计 ) ? 用过哪些分库分表中间件 ? 不同的分库分表中间件都有什么...【详细内容】
2021-06-18  Tags: 高并发  点击:(119)  评论:(0)  加入收藏
1. 目的撰写本文的目的是解决微服务架构,对静态数据资源没有规整,所有微服务都是从数据库直接读取,导致性能较差,用户体验不好。通常在高可用的分布式架构中,一般都会采用将这部...【详细内容】
2021-03-17  Tags: 高并发  点击:(157)  评论:(0)  加入收藏
元旦期间 订单业务线 告知 推送系统 无法正常收发消息,作为推送系统维护者的我正外面潇洒,无法第一时间回去,直接让 ops 帮忙重启服务,一切好了起来,重启果然是个大杀器。由于推...【详细内容】
2021-01-07  Tags: 高并发  点击:(146)  评论:(0)  加入收藏
本文主要介绍的微服务是spring cloud,它一个服务治理框架和一系列框架的由序集合,其利用springboot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册、负载...【详细内容】
2020-10-20  Tags: 高并发  点击:(105)  评论:(0)  加入收藏
一、什么是分布式?分布式更多的是一个概念,是为了解决单个物理服务器容量和性能瓶颈问题而采用的优化手段,该领域需要解决的问题极多,在不同的技术层面上,又包括:分布式文件系统...【详细内容】
2020-10-14  Tags: 高并发  点击:(91)  评论:(0)  加入收藏
作为热点频出的电商系统,经常遇到高并发,热点秒杀的场景。我们在开发设计高并发海量业务请求的系统时,通常利用三板斧:缓存、降级和限流来保障系统稳定性。...【详细内容】
2020-09-27  Tags: 高并发  点击:(68)  评论:(0)  加入收藏
前言一台服务器并发TCP连接数可以有多少?如何支持从硬件和操作系统上支持单台服务器支持上万并发,支持百万千万,甚至上亿的并发著名的C10K并发连接问题是什么?C10M并发问题又是...【详细内容】
2020-09-01  Tags: 高并发  点击:(103)  评论:(0)  加入收藏
▌简易百科推荐
阿里云镜像源地址及安装网站地址https://developer.aliyun.com/mirror/centos?spm=a2c6h.13651102.0.0.3e221b111kK44P更新源之前把之前的国外的镜像先备份一下 切换到yumcd...【详细内容】
2021-12-27  干程序那些事    Tags:CentOS7镜像   点击:(1)  评论:(0)  加入收藏
前言在实现TCP长连接功能中,客户端断线重连是一个很常见的问题,当我们使用netty实现断线重连时,是否考虑过如下几个问题: 如何监听到客户端和服务端连接断开 ? 如何实现断线后重...【详细内容】
2021-12-24  程序猿阿嘴  CSDN  Tags:Netty   点击:(12)  评论:(0)  加入收藏
一. 配置yum源在目录 /etc/yum.repos.d/ 下新建文件 google-chrome.repovim /etc/yum.repos.d/google-chrome.repo按i进入编辑模式写入如下内容:[google-chrome]name=googl...【详细内容】
2021-12-23  有云转晴    Tags:chrome   点击:(7)  评论:(0)  加入收藏
一. HTTP gzip压缩,概述 request header中声明Accept-Encoding : gzip,告知服务器客户端接受gzip的数据 response body,同时加入以下header:Content-Encoding: gzip:表明bo...【详细内容】
2021-12-22  java乐园    Tags:gzip压缩   点击:(9)  评论:(0)  加入收藏
yum -y install gcc automake autoconf libtool makeadduser testpasswd testmkdir /tmp/exploitln -s /usr/bin/ping /tmp/exploit/targetexec 3< /tmp/exploit/targetls -...【详细内容】
2021-12-22  SofM    Tags:Centos7   点击:(7)  评论:(0)  加入收藏
Windows操作系统和Linux操作系统有何区别?Windows操作系统:需支付版权费用,(华为云已购买正版版权,在华为云购买云服务器的用户安装系统时无需额外付费),界面化的操作系统对用户使...【详细内容】
2021-12-21  卷毛琴姨    Tags:云服务器   点击:(6)  评论:(0)  加入收藏
参考资料:Hive3.1.2安装指南_厦大数据库实验室博客Hive学习(一) 安装 环境:CentOS 7 + Hadoop3.2 + Hive3.1 - 一个人、一座城 - 博客园1.安装hive1.1下载地址hive镜像路径 ht...【详细内容】
2021-12-20  zebra-08    Tags:Hive   点击:(9)  评论:(0)  加入收藏
以下是服务器安全加固的步骤,本文以腾讯云的CentOS7.7版本为例来介绍,如果你使用的是秘钥登录服务器1-5步骤可以跳过。1、设置复杂密码服务器设置大写、小写、特殊字符、数字...【详细内容】
2021-12-20  网安人    Tags:服务器   点击:(7)  评论:(0)  加入收藏
项目中,遇到了一个问题,就是PDF等文档不能够在线预览,预览时会报错。错误描述浏览器的console中,显示如下错误:nginx代理服务报Mixed Content: The page at ******** was loaded...【详细内容】
2021-12-17  mdong    Tags:Nginx   点击:(7)  评论:(0)  加入收藏
转自: https://kermsite.com/p/wt-ssh/由于格式问题,部分链接、表格可能会失效,若失效请访问原文密码登录 以及 通过密钥实现免密码登录Dec 15, 2021阅读时长: 6 分钟简介Windo...【详细内容】
2021-12-17  LaLiLi    Tags:SSH连接   点击:(16)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条