高并发服务设计

22 阅读3分钟

一、多线程服务架构设计

一种常见且高效的多线程服务器架构模式是主从线程模型。
主线程,承担着监听端口和接受新连接的重要职责,将连接分配给工作线程池中的某个工作线程
工作线程专注于与客户端进行数据的收发和处理工作

解决同步问题 互斥锁和条件变量等同步机制

并发控制策略

  • 无锁数据结构(通常依赖原子操作)

  • 读写锁:std::shared_mutex rw_mtx;
    rw_mtx.lock_shared():获取共享锁(读锁),允许多个线程同时持有共享锁进行读操作
    rw_mtx.lock():获取独占锁,此时其他线程无法获取任何锁,直到独占锁被释放

二、高并发三板斧:多进程、多线程、IO多路复用

1.多进程架构设计方式,用于提高并发性、隔离性和容错性。常见游戏服务器开发中
1)优势
稳定性:单个进程崩溃不会影响整个服务器(如战斗逻辑进程崩溃,登录进程仍可用)。
资源隔离:不同进程独占 CPU、内存资源,避免互相干扰。
扩展性:可通过增加进程实例横向扩展(如动态扩容地图服务器)。
安全性:敏感模块(如支付)可运行在独立进程,降低被攻击风险。

(2)适用场景
MMORPG:分离登录、地图、战斗、聊天等模块。
实时竞技游戏:独立进程处理不同比赛房间。
分布式服务器:跨物理机部署多个进程协作

三、无锁编程

无锁编程(Lock-Free Programming)是并发编程的一种重要技术,它避免了传统的锁机制(例如互斥锁、自旋锁等),并通过原子操作的方式确保线程的安全。无锁编程能够在多线程环境中显著提升程序的并发性和可伸缩性,减少线程之间的竞争、阻塞和上下文切换开销。

无锁编程原理,其实是依赖原子操作来确保线程的安全性,而不是使用锁。原子操作是在并发环境中不可分割的操作,确保了操作的完整性。常见的原子操作有:

  • 原子加减法: 对共享变量进行加法或减法操作,保证在多个线程并发执行时,操作是不可分割。

  • CAS(Compare and Swap,比较并交换): CAS是无锁编程的核心原子操作之一,主要用于条件性更新数据。它会比较内存中的值和期望值,如果相等则更新,否则不做操作。

  • 原子读写: 读取和写入值属于原子操作,确保并发操作的正确性。

应用场景?

无锁编程的不足之处

  • ABA问题
    ABA问题是在并发编程中常见的一个问题,特别是在使用无锁数据结构(如CAS,Compare-And-Swap)时。ABA问题指的是一个变量的值从A变为B,然后又变回A,虽然最终值仍然是A,但在这期间可能发生了其他操作,导致程序逻辑出错。
    在 CAS 操作中,ABA 问题指的是一个值在 CAS 检查和更新之间发生了变化,最终 CAS 仍然会认为值没有改变。为了解决 ABA 问题,通常可以通过引入版本号或者使用指针标记技术来标识值的变化。

四、压测

QPS queries per second
有两种计算公式:
QPS = req/sec = 请求数/秒
QPS = 总请求数 / ( 进程总数 * 请求时间 )
TPS transactions per second 每秒处理的事务次数。客户端请求服务端,服务端内部处理,服务端返回客户端