Node.js + Express的數據庫AB View切換方案設計

方案總覽

數據導入過程: ? ?

- 根據控制表判斷當前活躍組(假設當前活躍的是a,那么接下來要導入到b)。 ? ?

- 清空非活躍表(即b表)的數據,然后將新數據導入到b表。 ? ?

- 切換控制表,將活躍組改為b,這樣新的查詢就會使用view_b(指向table_b)。 ? ?

- 延遲1分鐘后清空原來的活躍表(即a表)的數據。

系統設計

1. 數據庫結構
-- 數據表
CREATE TABLE data_a (id SERIAL PRIMARY KEY, ...);
CREATE TABLE data_b (id SERIAL PRIMARY KEY, ...);-- 視圖(始終指向活躍表)
CREATE OR REPLACE VIEW current_data AS SELECT * FROM data_a; -- 初始指向A表-- 控制表(關鍵元數據)
CREATE TABLE ab_control (id SERIAL PRIMARY KEY,active_group CHAR(1) NOT NULL CHECK (active_group IN ('a','b')),next_switch_time TIMESTAMP
);
INSERT INTO ab_control(active_group) VALUES ('a'); -- 初始狀態--Powered by https://zhengkai.blog.csdn.net/
2. 狀態流轉邏輯
當前活躍組 | 操作步驟
-------------------------
A (初始)  → 導入數據到B表 → 切換視圖到B → (1分鐘后清空A表)→ 狀態變更為B
B         → 反向操作

Express 實現代碼

僅供參考,按照實際使用場景進行改造

const express = require('express');
const { Pool } = require('pg'); // 以PostgreSQL為例
const app = express();
app.use(express.json());// 數據庫配置
const pool = new Pool({...});// 獲取當前活躍組
async function getActiveGroup() {const res = await pool.query('SELECT active_group FROM ab_control LIMIT 1');return res.rows[0].active_group;
}// Powered by https://zhengkai.blog.csdn.net/
// 主切換函數
async function switchDataGroup(newData) {const client = await pool.connect();try {await client.query('BEGIN');// 1. 獲取當前狀態const { active_group } = (await client.query('SELECT active_group FROM ab_control FOR UPDATE')).rows[0];// 2. 確定目標組const targetGroup = active_group === 'a' ? 'b' : 'a';const targetTable = `data_${targetGroup}`;// 3. 清空目標表并導入數據await client.query(`TRUNCATE TABLE ${targetTable}`);await client.query(`INSERT INTO ${targetTable} (col1, col2) VALUES ${newData.map(d => `(${d.val1}, ${d.val2})`).join(',')}`);// 4. 切換視圖await client.query(`CREATE OR REPLACE VIEW current_data AS SELECT * FROM ${targetTable}`);// 5. 更新控制表await client.query(`UPDATE ab_control SET active_group = $1,next_switch_time = NOW() + INTERVAL '1 minute'`, [targetGroup]);await client.query('COMMIT');// 6. 啟動延遲清空任務(非事務內)setTimeout(() => clearOldTable(active_group), 60000); } finally {client.release();}
}// 延遲清空舊表
async function clearOldTable(oldGroup) {const client = await pool.connect();try {await client.query(`TRUNCATE TABLE data_${oldGroup}`);} finally {client.release();}
}// 數據導入路由
app.post('/import', async (req, res) => {try {await switchDataGroup(req.body.data);res.status(200).send('Import and switch successful');} catch (err) {console.error('Switch failed:', err);res.status(500).send('Switch operation failed');}
});// 查詢路由(始終使用統一視圖)
app.get('/data', async (req, res) => {const result = await pool.query('SELECT * FROM current_data');res.json(result.rows);
});app.listen(3000, () => console.log('Server running on port 3000'));

關鍵設計說明

  1. 原子性切換

    使用事務(BEGIN/COMMIT)確保:
    • 三者操作的原子性

    • 目標表清空+導入

    • 控制表更新

  2. 視圖解耦

    • current_data?視圖始終作為應用層統一查詢入口

    • 切換時動態重建視圖指向新物理表

  3. 延遲清理

    • 使用?setTimeout?實現1分鐘延遲清空

    • 避免阻塞主流程

    • 注意:生產環境建議用Redis/Kue等持久化定時任務

  4. 并發控制

    • SELECT ... FOR UPDATE?鎖控制表,防止并發切換

    • 視圖重建瞬間的查詢短暫阻塞可接受

  5. 故障恢復

    • 控制表記錄?next_switch_time?可用于:

      • 重啟后檢查未完成的清理任務

      • 監控切換狀態


生產環境增強建議

  1. 切換日志表

    CREATE TABLE ab_switch_log (switch_time TIMESTAMPTZ PRIMARY KEY,from_group CHAR(1),to_group CHAR(1),success BOOLEAN
    );
  2. 重試機制

    // 在clearOldTable中添加重試邏輯
    async function clearOldTable(group) {let attempts = 0;while (attempts < 3) {try {await pool.query(`TRUNCATE TABLE data_${group}`);return;} catch (err) {attempts++;await new Promise(r => setTimeout(r, 5000));}}// 告警通知
    }
  3. 維護接口

    // 手動觸發清理
    app.post('/force-clean', async (req, res) => {const { group } = req.body;await clearOldTable(group);res.send(`Cleaned data_${group}`);
    });
  4. 監控指標

    • 每次切換時記錄:切換耗時、數據量大小

    • 視圖查詢性能監控

此設計實現了平滑的AB表切換,確保服務連續性,同時通過延遲清理機制保障數據安全

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914434.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914434.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914434.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++_編程提升_temaplate模板_案例

類模板案例案例描述: 實現一個通用的數組類&#xff0c;要求如下&#xff1a;可以對內置數據類型以及自定義數據類型的數據進行存儲將數組中的數據存儲到堆區構造函數中可以傳入數組的容量提供對應的拷貝構造函數以及operator防止淺拷貝問題提供尾插法和尾刪法對數組中的數據進…

Win11系統安裝Anaconda環境極簡教程

Win11系統安裝Anaconda環境極簡教程 &#x1f4e5; 第一步&#xff1a;下載 Anaconda 安裝包 打開瀏覽器&#xff0c;訪問 Anaconda 官網&#xff0c;選擇View All Installers 選擇所需版本&#xff08;此文以2024.02-1為例&#xff09;&#xff0c;點擊進行下載&#xff08;…

Datawhale AI夏令營-基于帶貨視頻評論的用戶洞察挑戰賽

一.賽事目標基于星火大模型Spark 4.0 Ultra&#xff0c;對視頻和評論的數據進行商品識別&#xff0c;情感分析&#xff0c;歸類分析&#xff0c;最終為帶貨效果進行評價。并通過優化模型來提高評價準確度二.賽事環境1.基礎平臺&#xff1a;星火大模型Spark 4.0 Ultra2.賽事數據…

如何基于FFMPEG 實現視頻推拉流

文章目錄 前言環境準備為什么選擇 FFmpeg什么是nginx 1.7.11.3 GryphonNginx的conf配置啟動nginx推流命令接收視頻流Untiy播放視頻流最后前言 我們經常會有在電腦上實現推拉流的需求,Unity 和Unreal 都提供了基于WebRTC 的視頻流方案,效果還不錯,但是當我們需要推拉整個電腦…

飛算JavaAI:從情緒價值到代碼革命,智能合并項目與定制化開發新范式

目錄一、飛算 JavaAI 是什么&#xff1f;二、飛算JavaAI&#xff1a;安裝登錄2.1 IDEA插件市場安裝&#xff08;推薦&#xff09;2.2 離線安裝包三、飛算JavaAI核心功能&#xff1a;一鍵生成完整工程代碼功能背景3.1 理解需求3.2 設計接口3.3 表結構自動設計3.4 處理邏輯&#…

Python 基礎語法與數據類型(十一) - 類 (class) 與對象 (實例)

文章目錄1. 什么是類 (Class)&#xff1f;1.1 定義一個類2. 什么是對象 (Object) 或實例 (Instance)&#xff1f;2.1 創建對象&#xff08;實例化&#xff09;3. 訪問屬性和調用方法4. 類屬性 vs 實例屬性5. self 的重要性總結練習題練習題答案前幾篇文章我們學習了變量、數據類…

精準數據檢索+數據飛輪自驅優化,彩訊AI知識庫助力企業知識賦能和效率創新

近兩年&#xff0c;人工智能技術的精細化發展&#xff0c;讓知識庫概念重新成為“熱門詞匯”&#xff0c;騰訊ima等智能工作臺產品為個人用戶打造專屬知識庫&#xff0c;而面向B端市場&#xff0c;企業AI知識庫也逐步成為企業集中存儲與管理核心文檔、數據、經驗和流程的知識中…

打破空間邊界!Nas-Cab用模塊化設計重構個人存儲邏輯

文章目錄前言1. Windows安裝Nas-Cab2. 本地局域網連接Nas-Cab3. 安裝Cpolar內網穿透4. 固定Nas-Cab 公網地址"數據管理不該受制于硬件形態或地理邊界。這個開源方案證明&#xff1a;當功能模塊化且可擴展時&#xff0c;私有云可以像水一樣滲透進所有設備——現在就去Git倉…

Sigma-Aldrich細胞培養基礎知識:細胞培養的安全注意事項

細胞培養實驗室風險評估風險評估的主要目的是防止人員受傷&#xff0c;保護財產&#xff0c;并避免對個人和環境的傷害。在許多國家&#xff0c;法律要求進行風險評估。例如&#xff0c;英國的《英國職業健康與安全法案&#xff08;1974年&#xff09;》就是一個例子。歐洲共同…

Imx6ull用網線與電腦連接

理解工作方式沒有路由器時&#xff0c;可以使用&#xff0c;只要保持虛擬機的兩個網卡一個與電腦在同一網,一個與板子在同一網段(保持通信)就可以從虛擬機往板子下載第一步&#xff1a;查看電腦連接的網絡這一步是在找到主機ip地址這兩步在其他同類教程里一樣的第二步:設置以太…

力扣454.四數相加Ⅱ

給你四個整數數組 nums1、nums2、nums3 和 nums4 &#xff0c;數組長度都是 n &#xff0c;請你計算有多少個元組 (i, j, k, l) 能滿足&#xff1a;0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] nums4[l] 0示例 1&#xff1a;輸入&#xff1a;nums1 [1,2], nums2 …

Joplin:一款免費開源、功能強大且注重隱私的筆記軟件

Joplin 是一款免費開源、功能強大且注重隱私的筆記和待辦事項應用程序&#xff0c;它的設計目標是成為 Evernote 等流行筆記應用的強大替代品&#xff0c;尤其適合重視數據所有權和隱私的用戶。 功能特性 Joplin 的核心定位與優勢如下&#xff1a; 完全開源&#xff1a;代碼公…

滲透前四天總結

目錄 一.DNS DNS 基本概述 DNS解析過程 二.HTTPS TLS握手過程 RSA加密 對稱加密&#xff1a; 非對稱加密&#xff1a; RSA加密過程 三.使用xdebug調試php 四.信息收集 一.DNS DNS 基本概述 DNS&#xff1a;域名系統(DomainNameSystem)因特網的一項核心服務&#xf…

Python----NLP自然語言處理(中文分詞器--jieba分詞器)

一、介紹文本語料在輸送給NLP模型前&#xff0c;需要一系列的預處理工作&#xff0c;才能符合模型輸入的要求。對于NLP來說&#xff0c;他學習一篇人類書寫的文章不是整體的來學習&#xff0c;而是一個詞一個詞的來學習。所以文本預處理的第一個步驟就是對文本進行分詞處理。&a…

深入了解linux系統—— 進程信號的保存

信號 信號&#xff0c;什么是信號&#xff1f; 在現實生活中&#xff0c;鬧鐘&#xff0c;紅綠燈&#xff0c;電話鈴聲等等&#xff1b;這些都是現實生活中的信號&#xff0c;當鬧鐘想起時&#xff0c;我就要起床&#xff1b;當電話鈴聲想起時&#xff0c;我就知道有人給我打電…

Redis 事務錯誤處理機制與開發應對策略

&#x1f4d8; Redis 事務錯誤處理機制與開發應對策略一、Redis 事務基礎回顧 Redis 中的事務由以下三組命令構成&#xff1a;命令作用說明MULTI開始一個事務&#xff0c;進入命令入隊模式命令集所有后續命令不會立即執行&#xff0c;而是入隊等待提交EXEC提交事務&#xff0c;…

信息學奧賽一本通 1549:最大數 | 洛谷 P1198 [JSOI2008] 最大數

【題目鏈接】 ybt 1549&#xff1a;最大數 洛谷 P1198 [JSOI2008] 最大數 【題目考點】 1. 線段樹&#xff1a;單點修改 區間查詢 知識點講解見&#xff1a;洛谷 P3374 【模板】樹狀數組 1&#xff08;線段樹解法&#xff09; 【解題思路】 本題為設線段樹維護區間最值&a…

【STM32】什么在使能寄存器或外設之前必須先打開時鐘?

這篇文章解釋一個非常基礎但是重要的問題&#xff1a; 為什么在使能寄存器或外設之前必須先打開時鐘&#xff1f; 我們會發現&#xff0c;如果不開時鐘就訪問寄存器 ? 會“寫不進去”或“讀取錯誤”。 因此&#xff0c;我們在寫代碼時&#xff0c;總是需要 先開時鐘&#xff0…

Go·并發處理http請求實現

一、Goroutine介紹 基本原理 goroutine 是 Go 運行時(Runtime)管理的??用戶態線程。與線程相比,其初始棧空間僅約 2KB,創建和切換的開銷更低,能夠同時運行大量并發任務。 創建goroutine的方法非常簡單,在將要調用的函數前加入go關鍵字即可。 func hello() {fmt.Pri…

USB一線連多屏?Display Link技術深度解析

DisplayLink 技術是一種基于USB接口的顯示輸出解決方案&#xff0c;通常用于通過USB端口連接多個顯示器&#xff0c;尤其在筆記本電腦、平板電腦和臺式機上&#xff0c;能夠顯著擴展顯示屏的數量和分辨率。它的核心技術原理是通過壓縮和傳輸圖形數據&#xff0c;將視頻信號通過…