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

直播必備!Spring Boot 實現(xiàn)高并發(fā)觀眾統(tǒng)計功能的技術(shù)方案揭秘

開發(fā) 前端
通過 Redis 的高并發(fā)處理能力,結(jié)合 Spring Boot 提供的 REST 接口和 WebSocket 推送機制,我們可以實現(xiàn)一個既輕量又高效的直播觀眾統(tǒng)計系統(tǒng)。

隨著直播平臺用戶數(shù)量激增,實時觀眾統(tǒng)計功能成為衡量直播間熱度和服務(wù)質(zhì)量的核心指標之一。然而,在高并發(fā)場景下,如何保證統(tǒng)計數(shù)據(jù)的準確性與系統(tǒng)性能,是一個關(guān)鍵技術(shù)挑戰(zhàn)。本文將深入探討如何基于 Spring Boot 框架,構(gòu)建一個支持高并發(fā)、低延遲、可擴展的觀眾統(tǒng)計系統(tǒng)。

系統(tǒng)需求分析

功能需求

  • 實時統(tǒng)計每個直播間的在線觀眾人數(shù)。
  • 支持觀眾進入、退出時的即時更新。
  • 提供 REST API 接口供前端定時拉取或后端推送使用。
  • 支持 WebSocket 實時推送觀眾人數(shù)變化。

技術(shù)挑戰(zhàn)

  • 并發(fā)量高:直播高峰期間同一直播間可能存在上萬并發(fā)連接。
  • 數(shù)據(jù)一致性:進入、退出直播間事件頻繁,需精準計算。
  • 系統(tǒng)性能:避免頻繁操作數(shù)據(jù)庫導(dǎo)致性能瓶頸。

系統(tǒng)架構(gòu)設(shè)計

+----------------+         +------------------+         +------------------+
|  Web Frontend  | <-----> |  Spring Boot API | <-----> | Redis In-Memory  |
|  (WebSocket)   |         |  + WebSocket     |         |    Store         |
+----------------+         +------------------+         +------------------+
                                                              |
                                                              v
                                                      +---------------+
                                                      |  MySQL (持久化) |
                                                      +---------------+

核心組件

  • Spring Boot API:提供 REST 接口與 WebSocket 服務(wù)。
  • Redis:作為高性能計數(shù)器,用于記錄各直播間實時觀眾數(shù)。
  • MySQL:作為歷史數(shù)據(jù)的持久化存儲。

技術(shù)實現(xiàn)方案(含代碼)

Redis 結(jié)構(gòu)設(shè)計

  • 使用 Hash + Set 結(jié)構(gòu)保存直播間觀眾信息。
Key: live:room:{roomId}:viewers
Type: Set
Value: 用戶唯一標識(userId 或 sessionId)


Key: live:room:{roomId}:viewerCount
Type: String
Value: 當前觀眾人數(shù)

用戶進入/退出直播間邏輯

我們通過 Redis 的 Set 來記錄唯一用戶 ID,同時通過計數(shù)器確保人數(shù)準確。

@Service
public class LiveViewerService {


    @Autowired
    private StringRedisTemplate redisTemplate;


    private static final String VIEWER_SET_KEY = "live:room:%s:viewers";
    private static final String COUNT_KEY = "live:room:%s:viewerCount";


    /**
     * 用戶進入直播間
     */
    public void userEnter(String roomId, String userId) {
        String viewerSetKey = String.format(VIEWER_SET_KEY, roomId);
        String countKey = String.format(COUNT_KEY, roomId);


        // 添加用戶到觀眾集合
        Boolean isNew = redisTemplate.opsForSet().add(viewerSetKey, userId) == 1;
        if (isNew) {
            // 若是新用戶,人數(shù) +1
            redisTemplate.opsForValue().increment(countKey);
        }
    }


    /**
     * 用戶退出直播間
     */
    public void userExit(String roomId, String userId) {
        String viewerSetKey = String.format(VIEWER_SET_KEY, roomId);
        String countKey = String.format(COUNT_KEY, roomId);


        // 移除用戶
        Boolean removed = redisTemplate.opsForSet().remove(viewerSetKey, userId) == 1;
        if (removed) {
            redisTemplate.opsForValue().decrement(countKey);
        }
    }


    /**
     * 獲取直播間當前觀眾人數(shù)
     */
    public Long getViewerCount(String roomId) {
        String countKey = String.format(COUNT_KEY, roomId);
        String count = redisTemplate.opsForValue().get(countKey);
        return count == null ? 0 : Long.parseLong(count);
    }
}
REST 接口示例
@RestController
@RequestMapping("/api/live")
public class LiveController {


    @Autowired
    private LiveViewerService viewerService;


    @PostMapping("/enter")
    public ResponseEntity<String> enter(@RequestParam String roomId, @RequestParam String userId) {
        viewerService.userEnter(roomId, userId);
        return ResponseEntity.ok("entered");
    }


    @PostMapping("/exit")
    public ResponseEntity<String> exit(@RequestParam String roomId, @RequestParam String userId) {
        viewerService.userExit(roomId, userId);
        return ResponseEntity.ok("exited");
    }


    @GetMapping("/count")
    public ResponseEntity<Long> getCount(@RequestParam String roomId) {
        return ResponseEntity.ok(viewerService.getViewerCount(roomId));
    }
}

WebSocket 實時推送實現(xiàn)

@ServerEndpoint("/ws/viewerCount/{roomId}")
@Component
public class ViewerCountWebSocket {


    private static Map<String, Set<Session>> roomSessions = new ConcurrentHashMap<>();


    @OnOpen
    public void onOpen(Session session, @PathParam("roomId") String roomId) {
        roomSessions.computeIfAbsent(roomId, k -> ConcurrentHashMap.newKeySet()).add(session);
    }


    @OnClose
    public void onClose(Session session, @PathParam("roomId") String roomId) {
        Set<Session> sessions = roomSessions.get(roomId);
        if (sessions != null) {
            sessions.remove(session);
        }
    }


    public static void broadcastViewerCount(String roomId, Long count) {
        Set<Session> sessions = roomSessions.get(roomId);
        if (sessions != null) {
            for (Session session : sessions) {
                session.getAsyncRemote().sendText(count.toString());
            }
        }
    }
}

在 LiveViewerService 中用戶每次進入或退出后,調(diào)用:

ViewerCountWebSocket.broadcastViewerCount(roomId, getViewerCount(roomId));

即可實時推送更新。

前端集成示例 (Thymeleaf + JavaScript)

<script>
  const roomId = "10001";
  const socket = new WebSocket("ws://localhost:8080/ws/viewerCount/" + roomId);


  socket.onmessage = function(event) {
    document.getElementById("viewerCount").innerText = event.data;
  };
</script>
<span>當前觀眾人數(shù):<strong id="viewerCount">0</strong></span>

系統(tǒng)優(yōu)化建議

  • Redis 原子性保障:使用 Lua 腳本處理計數(shù)與集合操作,避免競態(tài)。
  • 斷開連接處理:使用心跳機制或定時任務(wù)清理無效連接。
  • Redis 過期策略:為每個 Set 設(shè)置過期時間,避免垃圾數(shù)據(jù)堆積。
  • 數(shù)據(jù)持久化:定期將統(tǒng)計數(shù)據(jù)寫入數(shù)據(jù)庫,供歷史分析使用。

總結(jié)

通過 Redis 的高并發(fā)處理能力,結(jié)合 Spring Boot 提供的 REST 接口和 WebSocket 推送機制,我們可以實現(xiàn)一個既輕量又高效的直播觀眾統(tǒng)計系統(tǒng)。該方案不僅能應(yīng)對大量用戶同時在線的場景,還具備良好的可擴展性與實時性,是現(xiàn)代直播平臺不可或缺的基礎(chǔ)能力。

責(zé)任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2025-02-10 08:20:09

2024-08-01 11:38:40

2022-03-31 17:38:09

高并發(fā)系統(tǒng)架構(gòu)設(shè)計負載均衡

2024-03-14 08:57:04

高并發(fā)緩存更新

2025-05-14 04:00:00

2024-10-31 09:04:20

Spring高并發(fā)

2025-06-12 02:00:00

Spring簽到打卡

2024-01-04 18:01:55

高并發(fā)SpringBoot

2024-10-15 16:01:19

SpringBoot緩存預(yù)熱

2022-02-08 17:07:54

Spring BooSpring Aop日志記錄

2023-04-17 23:49:09

開發(fā)代碼Java

2019-12-25 09:49:12

WebKitWindowsChrome

2019-01-24 09:42:55

系統(tǒng)高并發(fā)面試

2025-06-19 07:33:40

Springresources讀取

2025-05-27 03:33:00

Spring高并發(fā)接口

2021-07-19 09:25:19

數(shù)據(jù)庫MySQL技術(shù)

2022-01-26 07:01:00

開源社區(qū)項目

2012-04-24 09:30:57

淘寶開發(fā)

2024-08-29 09:01:39

2024-09-10 10:42:27

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲激情在线观看 | 黄色国产视频 | 国产99免费视频 | 99视频在线免费观看 | 色婷婷精品久久二区二区蜜臂av | 一级黄色毛片 | 国产精品高清一区二区 | 一区二区三区四区国产 | 在线观看a视频 | 亚洲小视频 | 成人一区二区在线 | 久久不射电影网 | 俺去俺来也www色官网cms | 久久精品国产v日韩v亚洲 | 成年免费大片黄在线观看岛国 | 亚洲成人一级片 | 久久精品亚洲一区二区三区浴池 | 亚洲国产网 | 久久久91 | 国产乱码精品一区二区三区忘忧草 | 国产黄色大片 | 国产精品久久影院 | 日韩欧美国产精品一区二区 | 精品综合久久 | 91精品国产91久久久久久吃药 | 中文字幕免费中文 | 在线观看国产h | 欧美成人免费在线 | 玖玖玖在线 | 亚洲色图网址 | 亚洲国产精品一区二区久久 | 欧美日韩国产欧美 | 精品欧美一区二区精品久久久 | a国产视频 | 欧美一级全黄 | 五月网婷婷 | 欧美性一级 | sese视频在线观看 | 天堂在线中文 | 国产黄色小视频 | 久久综合久 |