作者:booleanwang,腾讯PCG后台开发工程师
“N高N可”,高性能、高并发、高可用、高可靠、可扩展、可维护、可用性等是后台开发耳熟能详的词了,它们中有些词在大部分情况下表达相近意思。本序列文章旨在探讨和总结后台架构设计中常用的技术和方法,并归纳成一套方法论。
前言本文主要探讨和总结服务架构设计中高性能的技术和方法,如下图的思维导图所示,左边部分主要偏向于编程应用,右边部分偏向于组件应用,文章将按图中的内容展开。
高性能思维导图1无锁化大多数情况下,多线程处理可以提高并发性能,但如果对共享资源的处理不当,严重的锁竞争也会导致性能的下降。面对这种情况,有些场景采用了无锁化设计,特别是在底层框架上。无锁化主要有两种实现,串行无锁和数据结构无锁。
1.1串行无锁无锁串行最简单的实现方式可能就是单线程模型了,如redis/Nginx都采用了这种方式。在网络编程模型中,常规的方式是主线程负责处理I/O事件,并将读到的数据压入队列,工作线程则从队列中取出数据进行处理,这种半同步/半异步模型需要对队列进行加锁,如下图所示:
单Reactor多线程模型上图的模式可以改成无锁串行的形式,当MainReactoraccept一个新连接之后从众多的SubReactor选取一个进行注册,通过创建一个Channel与I/O线程进行绑定,此后该连接的读写都在同一个线程执行,无需进行同步。
主从Reactor职责链模型1.2结构无锁利用硬件支持的原子操作可以实现无锁的数据结构,很多语言都提供CAS原子操作(如go中的atomic包和C++11中的atomic库),可以用于实现无锁队列。我们以一个简单的线程安全单链表的插入操作来看下无锁编程和普通加锁的区别。
templatetypenameTstructNode{Node(constTvalue):data(value){}Tdata;Node*next=nullptr;};
有锁链表WithLockList:
templatetypenameTclassWithLockList{mutexmtx;NodeT*head;public:voidpushFront(constTvalue){auto*node=newNodeT(value);lock_guardmutexlock(mtx);//①node-next=head;head=node;}};
无锁链表LockFreeList:
templatetypenameTclassLockFreeList{atomicNodeT*head;public:voidpushFront(constTvalue){auto*node=newNodeT(value);node-next=head.load();while(!head.