成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

100萬QPS短鏈系統如何設計?

開發 前端
為了從根本上改善這一痛點,本文將系統介紹如何基于 Spring Boot 3.4.5 + Spring Cloud Context 實現無需重啟即可動態更新配置文件的機制,覆蓋原理解析、實戰代碼、注意事項,助你提升至少 50% 的配置變更效率。

前言

凌晨兩點,監控大屏突然飆紅——短鏈服務QPS突破80萬! 數據庫連接池告急,Redis集群響應延遲突破500ms。

這不是演習,而是某電商平臺大促的真實場景。

當每秒百萬級請求涌向你的短鏈服務,你該如何設計系統?

今天這篇文章跟大家一起聊聊100萬QPS短鏈系統要如何設計?

希望對你會有所幫助。

最近建了一些工作內推群,各大城市都有,歡迎各位HR和找工作的小伙伴進群交流,群里目前已經收集了不少的工作內推崗位。

1.短鏈系統的核心挑戰

首先我們一起看看設計一個高并發的短鏈系統,會遇到哪些核心的挑戰。

如下圖所示:

圖片圖片

百萬QPS下的三大生死關:

  • ID生成瓶頸:傳統數據庫自增ID撐不住百萬并發
  • 跳轉性能黑洞:302重定向的TCP連接成本
  • 緩存雪崩風險:熱點短鏈瞬間擊穿Redis

2.短鏈生成

2.1 發號器的設計

發號器是短鏈系統的發動機。

方案對比:

方案

吞吐量

缺點

適用場景

UUID

5萬/s

長度長,無法排序

小型系統

Redis自增ID

8萬/s

依賴緩存持久化

中型系統

Snowflake

12萬/s

時鐘回撥問題

中大型系統

分段發號

50萬/s

需要預分配

超大型系統

分段發號器實現(Java版):

public class SegmentIDGen {
    privatefinal AtomicLong currentId = new AtomicLong(0);
    privatevolatilelong maxId;
    privatefinal ExecutorService loader = Executors.newSingleThreadExecutor();

    public void init() {
        loadSegment();
        loader.submit(this::daemonLoad);
    }

    private void loadSegment() {
        // 從DB獲取號段:SELECT max_id FROM alloc WHERE biz_tag='short_url'
        this.maxId = dbMaxId + 10000; // 每次取1萬個號
        currentId.set(dbMaxId);
    }

    private void daemonLoad() {
        while (currentId.get() > maxId * 0.8) {
            loadSegment(); // 號段使用80%時異步加載
        }
    }

    public long nextId() {
        if (currentId.get() >= maxId) thrownew BusyException();
        return currentId.incrementAndGet();
    }
}

關鍵優化

  • 雙Buffer異步加載(避免加載阻塞)
  • 監控號段使用率(動態調整步長)
  • 多實例分段隔離(biz_tag區分業務)

2.2 短鏈映射算法

短碼映射將長ID轉換成62進制的字符串。

轉換原理:

2000000000 = 2×62^4 + 17×62^3 + 35×62^2 + 10×62 + 8 
           = "Cdz9a"

原始ID: 2000000000,轉換為62進制的值為Cdz9a。

// Base62編碼(0-9a-zA-Z)
publicclass Base62Encoder {
    privatestaticfinal String BASE62 = 
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    
    public static String encode(long id) {
        StringBuilder sb = new StringBuilder();
        while (id > 0) {
            sb.append(BASE62.charAt((int)(id % 62)));
            id /= 62;
        }
        return sb.reverse().toString();
    }
    
    // 測試:生成8位短碼
    public static void main(String[] args) {
        long id = 1_000_000_000L;
        System.out.println(encode(id)); // 輸出:BFp3qQ
    }
}

編碼優勢:

  • 6位短碼可表示 62^6 ≈ 568億種組合
  • 8位短碼可表示 62^8 ≈ 218萬億種組合
  • 無意義字符串避免被猜測

3.存儲架構

3.1 數據存儲模型設計

圖片圖片

3.2 緩存層級設計

圖片圖片

3.3 緩存擊穿解決方案

// Redis緩存擊穿防護
public String getLongUrl(String shortCode) {
    // 1. 布隆過濾器預檢
    if (!bloomFilter.mightContain(shortCode)) {
        returnnull;
    }
    
    // 2. 查Redis
    String cacheKey = "url:" + shortCode;
    String longUrl = redis.get(cacheKey);
    if (longUrl != null) {
        return longUrl;
    }
    
    // 3. 獲取分布式鎖
    String lockKey = "lock:" + shortCode;
    if (redis.setnx(lockKey, "1", 10)) { // 10秒超時
        try {
            // 4. 二次檢查緩存
            longUrl = redis.get(cacheKey);
            if (longUrl != null) return longUrl;
            
            // 5. 查數據庫
            longUrl = db.queryLongUrl(shortCode);
            if (longUrl != null) {
                // 6. 回填Redis
                redis.setex(cacheKey, 3600, longUrl);
            }
            return longUrl;
        } finally {
            redis.del(lockKey);
        }
    } else {
        // 7. 等待重試
        Thread.sleep(50);
        return getLongUrl(shortCode);
    }
}

防護要點:

  • 布隆過濾器攔截非法短碼
  • 分布式鎖防止緩存擊穿
  • 雙重檢查減少DB壓力
  • 指數退避重試策略

4.跳轉優化

4.1 Nginx層直接跳轉

server {
    listen 80;
    server_name s.domain.com;

    location ~ ^/([a-zA-Z0-9]{6,8})$ {
        set $short_code $1;

        # 查詢Redis
        redis_pass redis_cluster;
        redis_query GET url:$short_code;

        # 命中則直接302跳轉
        if ($redis_value != "") {
            add_header Cache-Control "private, max-age=86400";
            return 302 $redis_value;
        }

        # 未命中轉發到后端
        proxy_pass http://backend;
    }
}

性能收益:

  • 跳轉延遲從100ms降至5ms
  • 節省后端服務器資源
  • 支持百萬級并發連接

4.2 連接池優化

連接池優化可以用Netty實現:

// Netty HTTP連接池配置
publicclass HttpConnectionPool {
    privatefinal EventLoopGroup group = new NioEventLoopGroup();
    privatefinal Bootstrap bootstrap = new Bootstrap();
    
    public HttpConnectionPool() {
        bootstrap.group(group)
            .channel(NioSocketChannel.class)
            .option(ChannelOption.SO_KEEPALIVE, true)
            .handler(new HttpClientInitializer());
    }
    
    public Channel getChannel(String host, int port) throws InterruptedException {
        return bootstrap.connect(host, port).sync().channel();
    }
    
    // 使用示例
    public void redirect(ChannelHandlerContext ctx, String longUrl) {
        Channel channel = getChannel("target.com", 80);
        channel.writeAndFlush(new DefaultFullHttpRequest(
            HttpVersion.HTTP_1_1, 
            HttpMethod.GET, 
            longUrl
        ));
        // 處理響應...
    }
}

優化效果:

  • TCP連接復用率提升10倍
  • 減少80%的TCP握手開銷
  • QPS承載能力提升3倍

5.百萬QPS整體架構

百萬QPS整體架構如下圖所示:

圖片圖片

核心組件解析:

1)接入層

  • CDN:緩存靜態資源
  • Nginx:處理302跳轉,本地緩存熱點數據

2)緩存層

  • Redis集群:緩存短鏈映射
  • 布隆過濾器:攔截非法請求

3)服務層

  • 短鏈生成:分布式ID服務
  • 映射查詢:高并發查詢服務

4)存儲層

  • MySQL:分庫分表存儲映射關系
  • TiKV:分布式KV存儲ID生成狀態

6.容災設計

6.1 限流熔斷策略

基于Sentinel的熔斷降級:

public class RedirectController {
    @GetMapping("/{shortCode}")
    @SentinelResource(
        value = "redirectService", 
        fallback = "fallbackRedirect",
        blockHandler = "blockRedirect"
    )
    public ResponseEntity redirect(@PathVariable String shortCode) {
        // 跳轉邏輯...
    }
    
    // 熔斷降級方法
    public ResponseEntity fallbackRedirect(String shortCode, Throwable ex) {
        return ResponseEntity.status(503)
            .body("服務暫時不可用");
    }
    
    // 限流處理方法
    public ResponseEntity blockRedirect(String shortCode, BlockException ex) {
        return ResponseEntity.status(429)
            .body("請求過于頻繁");
    }
}

6.2 多級降級方案

使用多級降級方案:

圖片圖片

保證服務的高可用。

6.3 數據分片策略

基于短碼分庫分表:

public int determineDbShard(String shortCode) {
    // 取短碼首字母的ASCII值
    int ascii = (int) shortCode.charAt(0);
    // 分16個庫
    return ascii % 16;
}

public int determineTableShard(String shortCode) {
    // 取短碼的CRC32值
    CRC32 crc32 = new CRC32();
    crc32.update(shortCode.getBytes());
    // 每庫1024張表
    return (int) (crc32.getValue() % 1024);
}

這里成了16個庫,每個庫有1024張表。

7.性能壓測數據對比

優化點

優化前QPS

優化后QPS

提升倍數

原始方案

12,000

-

1x

+Redis緩存

120,000

10x


+Nginx直跳

350,000

2.9x


+連接池優化

780,000

2.2x


+布隆過濾器

1,200,000

1.5x



壓測環境:32核64G服務器 × 10臺,千兆內網

總結

百萬QPS短鏈架構核心要點如圖所示:

圖片圖片

四大設計原則:

  • 無狀態設計:跳轉服務完全無狀態,支持無限擴展
  • 讀多寫少優化:將讀性能壓榨到極致
  • 分而治之:數據分片,流量分散
  • 柔性可用:寧可部分降級,不可全線崩潰

真正的架構藝術不在于復雜,而在于在百萬QPS洪流中,用最簡單的路徑解決問題。當你的系統能在流量風暴中優雅舞蹈,才是架構師的巔峰時刻。

責任編輯:武曉燕 來源: 蘇三說技術
相關推薦

2022-09-13 17:45:40

長網址短鏈系統

2024-11-12 08:13:09

2024-11-19 16:31:23

2022-10-09 14:15:42

短鏈設計

2022-09-13 08:01:58

短鏈服務哈希算法字符串

2023-08-10 10:13:35

轉轉短鏈平臺

2025-06-04 03:15:00

高并發短鏈系統

2023-07-26 13:29:43

高性能短鏈系統

2025-04-30 08:56:34

2024-07-22 11:48:42

2019-05-05 09:28:59

架構數據查詢

2019-07-29 14:40:26

架構存儲檢索

2024-06-28 09:59:35

2015-05-15 13:21:22

URL系統設計

2022-11-21 09:57:18

網關系統

2025-04-27 01:22:00

QPS高并發MySQL

2025-04-27 10:10:04

2022-02-09 20:50:46

短鏈系統場景

2018-09-20 09:33:38

單機QPSRedis

2009-03-02 09:13:00

LinuxFedora操作系統
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一区二区三区网站 | 国产一区二区精品自拍 | 97超碰在线播放 | www.黄色网 | 日韩午夜在线观看 | 国产在线观看不卡一区二区三区 | 国产精品日韩欧美 | 亚洲天堂成人在线视频 | 国产91久久久久 | 看一级毛片 | 日韩精品一区二区三区 | 黄色免费在线观看 | 国产成人精品午夜视频免费 | 国产精品久久久久久久毛片 | 精品国产乱码久久久久久蜜柚 | 欧美一区二区在线视频 | 激情婷婷 | 亚洲视频在线观看免费 | 久久成人综合 | 五十女人一级毛片 | 国产激情精品视频 | 日韩最新网址 | 亚洲国产精品视频 | 中文字幕免费在线 | 精品国产1区2区3区 一区二区手机在线 | 天天干精品 | 超碰97免费在线 | 日韩视频专区 | 久久在线 | 噜噜噜噜狠狠狠7777视频 | 午夜精品久久久久久久久久久久 | 久久人爽爽人爽爽 | 国产中文视频 | 国产精品1区2区 | 情侣酒店偷拍一区二区在线播放 | 亚洲午夜视频 | 国产成人精品999在线观看 | www成人免费 | 日日噜 | 精品国产乱码久久久久久88av | 国产有码 |