最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mysql + nest.js  加鎖搞并發(fā)問題的實(shí)現(xiàn)

 更新時間:2026年03月08日 08:29:55   作者:張洪權(quán)  
本文主要介紹了使用NestJS和MySQL實(shí)現(xiàn)秒殺系統(tǒng)的庫存扣減,并解決了高并發(fā)超賣問題,通過原子SQL、NestJS原生SQL實(shí)現(xiàn)以及使用Redis和消息隊(duì)列等方案,可以有效提高系統(tǒng)的性能和穩(wěn)定性,

我給你一個 真實(shí)項(xiàng)目級的例子
NestJS + MySQL 原生 SQL 實(shí)現(xiàn) 秒殺庫存扣減,并解決 高并發(fā)超賣問題。

這個例子是很多電商系統(tǒng)的核心邏輯。

一、數(shù)據(jù)庫設(shè)計(jì)

商品表

CREATE TABLE goods (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  stock INT NOT NULL,
  price DECIMAL(10,2),
  create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

訂單表

CREATE TABLE orders (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT,
  goods_id INT,
  create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

初始化庫存

INSERT INTO goods (name, stock, price)
VALUES ('iphone 15', 10, 8999);

二、問題:高并發(fā)超賣

如果代碼這樣寫:

const goods = await db.query('SELECT * FROM goods WHERE id = ?', [id])

if (goods.stock > 0) {
  await db.query('UPDATE goods SET stock = stock - 1 WHERE id = ?', [id])
}

1000 個請求會出現(xiàn):

庫存10
賣出去100

因?yàn)椋?/p>

讀取庫存不是原子操作

三、正確方案一(推薦):原子 SQL

最推薦的寫法:

UPDATE goods
SET stock = stock - 1
WHERE id = ? AND stock > 0;

優(yōu)點(diǎn):

單條 SQL
原子操作
不會超賣
性能極高

四、NestJS 原生 SQL 實(shí)現(xiàn)

使用 MySQL 連接池。

安裝:

npm install mysql2

數(shù)據(jù)庫服務(wù)

import { Injectable } from '@nestjs/common'
import * as mysql from 'mysql2/promise'

@Injectable()
export class MysqlService {

  pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: '123456',
    database: 'test',
    connectionLimit: 10
  })

  async query(sql: string, params?: any[]) {
    const [rows] = await this.pool.execute(sql, params)
    return rows
  }

}

五、秒殺 Service

import { Injectable } from '@nestjs/common'
import { MysqlService } from './mysql.service'

@Injectable()
export class SeckillService {

  constructor(private db: MysqlService) {}

  async buy(userId: number, goodsId: number) {

    // 1 扣庫存(原子SQL)
    const result: any = await this.db.query(
      `UPDATE goods 
       SET stock = stock - 1 
       WHERE id = ? AND stock > 0`,
      [goodsId]
    )

    if (result.affectedRows === 0) {
      return {
        message: '庫存不足'
      }
    }

    // 2 創(chuàng)建訂單
    await this.db.query(
      `INSERT INTO orders (user_id, goods_id) VALUES (?, ?)`,
      [userId, goodsId]
    )

    return {
      message: '秒殺成功'
    }

  }

}

六、Controller

import { Controller, Post, Body } from '@nestjs/common'
import { SeckillService } from './seckill.service'

@Controller('seckill')
export class SeckillController {

  constructor(private seckillService: SeckillService) {}

  @Post('buy')
  async buy(@Body() body) {

    const { userId, goodsId } = body

    return this.seckillService.buy(userId, goodsId)

  }

}

七、執(zhí)行流程(高并發(fā))

1000個請求:

UPDATE goods SET stock = stock - 1 WHERE id=1 AND stock>0

MySQL 內(nèi)部會保證:

庫存10

前10個請求成功
990個失敗

不會出現(xiàn):

stock = -1

八、真實(shí)大廠架構(gòu)(完整版)

真正秒殺系統(tǒng)通常是這樣:

用戶請求
   ↓
Nginx
   ↓
Redis 判斷庫存
   ↓
消息隊(duì)列 (Kafka / RabbitMQ)
   ↓
NestJS 消費(fèi)
   ↓
MySQL 扣庫存

作用:

Redis      防止打爆數(shù)據(jù)庫
MQ         削峰
MySQL      最終一致

九、如果必須用 MySQL Lock

有些復(fù)雜業(yè)務(wù)必須用:

SELECT * FROM goods WHERE id = 1 FOR UPDATE;

NestJS 示例:

const conn = await this.db.pool.getConnection()

try {

  await conn.beginTransaction()

  const [goods]: any = await conn.query(
    'SELECT * FROM goods WHERE id = ? FOR UPDATE',
    [goodsId]
  )

  if (goods.length === 0 || goods[0].stock <= 0) {
    await conn.rollback()
    return { message: '庫存不足' }
  }

  await conn.query(
    'UPDATE goods SET stock = stock - 1 WHERE id = ?',
    [goodsId]
  )

  await conn.query(
    'INSERT INTO orders (user_id, goods_id) VALUES (?, ?)',
    [userId, goodsId]
  )

  await conn.commit()

  return { message: '購買成功' }

} catch (err) {

  await conn.rollback()
  throw err

} finally {

  conn.release()

}

十、什么時候用哪種方案

方案推薦度場景
原子 UPDATE?????秒殺、庫存
事務(wù) + FOR UPDATE???復(fù)雜業(yè)務(wù)
Redis + MQ??????超高并發(fā)

?? 我再告訴你一個 90% 后端不知道的優(yōu)化技巧:

MySQL 秒殺最強(qiáng)寫法其實(shí)是:

UPDATE goods 
SET stock = stock - 1 
WHERE id = 1 AND stock > 0
LIMIT 1;

原因:

防止誤更新
鎖范圍更小

到此這篇關(guān)于mysql + nest.js 加鎖搞并發(fā)問題的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)mysql nest.js 加鎖并發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA鏈接MySQL報(bào)錯08001和連接成功后不顯示表的問題及解決方法

    IDEA鏈接MySQL報(bào)錯08001和連接成功后不顯示表的問題及解決方法

    這篇文章主要介紹了IDEA鏈接MySQL報(bào)錯08001和連接成功后不顯示表的問題及解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • MySQL創(chuàng)建用戶的三種方法

    MySQL創(chuàng)建用戶的三種方法

    在對MySQL的日常管理和操作中,為了避免有人惡意使用root用戶控制數(shù)據(jù)庫,盡可能地不用或少用 root 用戶登錄系統(tǒng),本文主要介紹了MySQL創(chuàng)建用戶的三種方法,感興趣的可以了解一下
    2023-08-08
  • MySQL版本選擇與安裝超詳細(xì)教程

    MySQL版本選擇與安裝超詳細(xì)教程

    本文主要介紹了MySQL5.5和MySQL8.0的優(yōu)點(diǎn)和缺點(diǎn),并建議大多數(shù)用戶使用最新的穩(wěn)定版本,此外還提供了MySQL的安裝教程和環(huán)境變量的配置方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • 在Windows主機(jī)上定時備份遠(yuǎn)程VPS(CentOS)數(shù)據(jù)的批處理

    在Windows主機(jī)上定時備份遠(yuǎn)程VPS(CentOS)數(shù)據(jù)的批處理

    我想在自己的 Windows7 下每天/周運(yùn)行一次備份,就有了這個小工具
    2012-05-05
  • MySQL系列之七 MySQL存儲引擎

    MySQL系列之七 MySQL存儲引擎

    存儲引擎是數(shù)據(jù)庫的核心,對于mysql來說,存儲引擎是以插件的形式運(yùn)行的。雖然mysql支持種類繁多的存儲引擎,但是常用的就那么幾種。這篇文章主要給大家介紹MySQL存儲引擎的相關(guān)知識,一起看看吧
    2021-07-07
  • 關(guān)于MYSQL的優(yōu)化全面詳解

    關(guān)于MYSQL的優(yōu)化全面詳解

    一直用了那么久的mysql,雖然了解了一些優(yōu)化方法,但是都是比較簡單的一些應(yīng)用,這次就系統(tǒng)的了解一下
    2012-09-09
  • MySql如何解決mysql沒有root用戶問題

    MySql如何解決mysql沒有root用戶問題

    文章主要描述了在MySQL中沒有root用戶的情況如何解決,首先,作者提到由于沒有root用戶,無法進(jìn)行后續(xù)的權(quán)限設(shè)置和操作,然后,作者詳細(xì)介紹了創(chuàng)建root用戶并賦予其所有權(quán)限的步驟,包括解決可能遇到的錯誤,最后,作者總結(jié)了整個過程,并希望大家能夠從中受益
    2025-02-02
  • 深入理解MySQL中的行級鎖

    深入理解MySQL中的行級鎖

    行級鎖加鎖規(guī)則比較復(fù)雜,不同的場景,加鎖的形式是不同的,本文主要介紹了深入理解MySQL中的行級鎖,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • MySQL數(shù)據(jù)庫基本SQL語句教程之高級操作

    MySQL數(shù)據(jù)庫基本SQL語句教程之高級操作

    對MySQL數(shù)據(jù)庫的查詢,除了基本的查詢外,有時候需要對查詢的結(jié)果集進(jìn)行處理,下面這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)庫基本SQL語句教程之高級操作的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • 詳解監(jiān)聽MySQL的binlog日志工具分析:Canal

    詳解監(jiān)聽MySQL的binlog日志工具分析:Canal

    Canal主要用途是基于MySQL數(shù)據(jù)庫增量日志解析,提供增量數(shù)據(jù)訂閱和消費(fèi),目前主要支持MySQL。接下來通過本文給大家介紹監(jiān)聽MySQL的binlog日志工具分析:Canal的相關(guān)知識,感興趣的朋友一起看看吧
    2020-10-10

最新評論

子长县| 大兴区| 义马市| 黑河市| 佳木斯市| 哈巴河县| 综艺| 库尔勒市| 轮台县| 安西县| 洛川县| 襄汾县| 曲阜市| 天台县| 宁明县| 瓦房店市| 天峨县| 克山县| 临武县| 亳州市| 璧山县| 景洪市| 台东县| 巴彦淖尔市| 海安县| 新乡市| 射阳县| 通榆县| 莫力| 喜德县| 东宁县| 杂多县| 夹江县| 佛坪县| 修水县| 左云县| 和平县| 丰都县| 永年县| 蒙阴县| 汪清县|