主頁 > 資料庫 > day05-優惠券秒殺01

day05-優惠券秒殺01

2023-04-25 08:31:23 資料庫

功能03-優惠券秒殺01

4.功能03-優惠券秒殺

4.1全域唯一ID

4.1.1全域ID生成器

每個店鋪都可以發布優惠券:

image-20230423154152138

當用戶搶購時,就會生成訂單,并保存到tb_voucher_order這張表中,訂單表如果使用資料庫的自增id就存在一些問題:

  1. id的規律性太明顯:用戶可以根據id猜測一些資訊,從而非法得到資料
  2. 受單表資料量的限制:由于單張表的資料限制,需要進行分表,而如果每張表都采取自增長,容易出現id重復,會影響訂單之后的業務,比如說售后服務(因為售后服務一般是根據訂單id來進行的)

解決方案:使用全域ID生成器,

(1)全域ID生成器是一種在分布式系統下用來生成全域唯一ID的工具(也稱為分布式唯一ID),一般要滿足下列特性:

  • 唯一性

  • 高可用

  • 高性能

  • 遞增性

  • 安全性

(2)全域唯一ID生成策略:

  • UUID
  • Redis自增
  • snowflake演算法
  • 資料庫自增

(3)我們這里使用redis作為全域唯一生成器的實作方案,原因如下:

  1. redis是獨立于資料庫之外的,它只有一個,當所有人都來訪問redis時,它的自增一定是唯一的(唯一性)

  2. 使用redis的集群、主從方案、哨兵功能,可以維持它的高可用性(高可用)

  3. redis具有高性能(高性能)

  4. 可以使用redis的String型別,具有自增性(如:incr命令)(自增性)

    Redis Incr 命令將 key 中儲存的數字值增一

    如果 key 不存在,那么 key 的值會先被初始化為 0 ,然后再執行 INCR 操作

  5. 為了增加id的安全性,我們不會直接使用自增redis自增的id,而是拼接一些其他資訊:(安全性)

    ID構造:時間戳+計數器(使用long型別,共八位元組,64bit)

    • 符號位:1bit,永遠為0

    • 時間戳:31bit,以秒為單位,可以使用約69年

    • 序列號:32bit,秒內的計數器,這樣可以支持每秒產生2^32個不同的ID

      image-20230423175259846

4.2Redis實作全域唯一ID

(1)創建全域ID生成器RedisIdWorker

package com.hmdp.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

/**
 * @author 李
 * @version 1.0
 */
@Component
public class RedisIdWorker {
    //開始時間戳(1970-01-01T00:00:00到2022-01-01T00:00:00的秒數)
    private static final long BEGIN_TIMESTAMP = 1640995200L;

    //序列號的位數
    private static final int COUNT_BITS = 32;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    //public static void main(String[] args) {
    //    //開始時間
    //    LocalDateTime time = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
    //    //得到1970-01-01T00:00:00Z.到指定時間為止的具體秒數
    //    long second = time.toEpochSecond(ZoneOffset.UTC);
    //    System.out.println(second);//1640995200L
    //}

    public long nextId(String keyPrefix) {
        //1.生成時間戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        //開始時間到當前時間的 時間戳
        long timeStamp = nowSecond - BEGIN_TIMESTAMP;

        //2.生成序列號(keyPrefix代表業務前綴)
        /*
         * Redis的 Incr命令將 key 中儲存的數字值增1,如果key不存在,那么key的值會先被初始化為0,然后再執行INCR操作,
         * 根據這個特性,我們每一天拼接不同的日期,當做key,也就是說同一天下單采用相同的key,不同天下單采用不同的key
         * 這種方法不僅可以防止訂單號使用完(redis的的自增最多可以有2^64位,我們采取其中32位作計數器),
         * 還可以根據不同的日期,統計該天的訂單數量
         */
        //2.1獲取當前的日期(精確到天)
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        //2.2做自增長
        Long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);

        //3.拼接并回傳
        //將時間戳左移32位,空出來的右邊32位使用count填充,共64位
        return timeStamp << COUNT_BITS | count;
    }
}

(2)測驗類(部分代碼)

@Resource
private RedisIdWorker redisIdWorker;
private ExecutorService es = Executors.newFixedThreadPool(500);

@Test
public void testIdWorker() throws InterruptedException {
    CountDownLatch latch = new CountDownLatch(300);
    //執行緒,生成100個id
    Runnable task = () -> {
        for (int i = 0; i < 100; i++) {
            long id = redisIdWorker.nextId("order");
            System.out.println("id" + id);
        }
        latch.countDown();
    };
    long start = System.currentTimeMillis();
    //共執行300次任務
    for (int i = 0; i < 300; i++) {
        es.submit(task);
    }
    //讓所有執行緒執行完才計時
    latch.await();
    long end = System.currentTimeMillis();
    System.out.println("共用時=" + (end - start));
}

關于countdownlatch

countdownlatch名為信號槍:主要的作用是同步協調在多執行緒的等待于喚醒問題,如果沒有CountDownLatch ,由于程式是異步的,當異步程式沒有執行完時,主執行緒可能就已經執行完了,如果期望的是分執行緒全部走完之后,主執行緒再走,此時就需要使用到CountDownLatch,CountDownLatch 中有兩個最重要的方法:1.countDown 2.await

await 方法是阻塞方法,使用await可以讓main執行緒阻塞,當CountDownLatch 內部維護的變數變為0時,就不再阻塞,直接放行,那么什么時候CountDownLatch 維護的變數變為0 呢?我們只需要呼叫一次countDown ,內部變數就減少1,

根據這個性質,讓分執行緒和變數系結, 執行完一個分執行緒就減少一個變數,當分執行緒全部走完,CountDownLatch 維護的變數就是0,此時await就不再阻塞,統計出來的時間也就是所有分執行緒執行完后的時間,

測驗結果:

image-20230423191756438

查看redis中的資料:對應的key的自增值已經變為30000,說明生成了3w個id

image-20230423195906103

4.2.1總結

全域唯一ID生成策略:

  • UUID
  • Redis自增
  • snowflake演算法
  • 資料庫自增(使用一張表來單獨記錄id)

Redis自增ID策略:

  • 每天一個key,方便統計訂單量
  • ID結構:時間戳+計數器

4.2實作優惠券秒殺下單

4.2.1需求分析&業務流程

每個店鋪都可以發布優惠券,分為平價券和特價券,平價券可以任意購買,而特價券需要秒殺搶購:

image-20230423201358147

這兩張券對應的資料庫表結構如下:

  • tb_voucher:(優惠券表)優惠券的基本資訊、優惠金額、使用規則等(包括平價券和秒殺券)

    image-20230424161312210
  • tb_seckill_voucher:(秒殺優惠券表)優惠券的庫存、開始搶購時間、結束搶購時間,秒殺優惠券才需要填寫這些資訊,

    image-20230424161158004

要求在店鋪詳情中實作下單購買秒殺券:

下單時需要判斷兩點:

  1. 秒殺是否開始或者結束,如果尚未開始或者已經結束則無法下單
  2. 秒殺券的庫存是否充足,不足則無法下單
image-20230424152833646

優惠券訂單表結構:

image-20230424161458352

業務流程分析:

image-20230424153759552

4.2.2代碼實作

(1)優惠券訂單物體:VoucherOrder.java

package com.hmdp.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 優惠券訂單物體
 * 
 * @author 李
 * @version 1.0
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_voucher_order")
public class VoucherOrder implements Serializable {
    private static final long serialVersionUID = 1L;
    //主鍵
    @TableId(value = "https://www.cnblogs.com/liyuelian/p/id", type = IdType.INPUT)
    private Long id;
    //下單的用戶id
    private Long userId;
    //購買的代金券id
    private Long voucherId;
    //支付方式 1:余額支付;2:支付寶;3:微信
    private Integer payType;
    //訂單狀態,1:未支付;2:已支付;3:已核銷;4:已取消;5:退款中;6:已退款
    private Integer status;
    //下單時間
    private LocalDateTime createTime;
    //支付時間
    private LocalDateTime payTime;
    //核銷時間
    private LocalDateTime useTime;
    //退款時間
    private LocalDateTime refundTime;
    //更新時間
    private LocalDateTime updateTime;
}

(2)mapper介面

package com.hmdp.mapper;

import com.hmdp.entity.VoucherOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 *  Mapper 介面
 *
 * @author 李
 * @version 1.0
 */
public interface VoucherOrderMapper extends BaseMapper<VoucherOrder> {

}

(3)IVoucherOrderService 服務類

package com.hmdp.service;

import com.hmdp.dto.Result;
import com.hmdp.entity.VoucherOrder;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 *  服務類
 *
 * @author 李
 * @version 1.0
 */
public interface IVoucherOrderService extends IService<VoucherOrder> {

    Result seckillVoucher(Long voucherId);
}

(4)VoucherOrderServiceImpl 服務實作類

package com.hmdp.service.impl;

import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisIdWorker;
import com.hmdp.utils.UserHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * 服務實作類
 *
 * @author 李
 * @version 1.0
 */
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
    @Resource
    private ISeckillVoucherService seckillVoucherService;
    @Resource
    private RedisIdWorker redisIdWorker;

    @Override
    @Transactional
    public Result seckillVoucher(Long voucherId) {
        //根據id查詢優惠券資訊
        SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
        if (voucher == null) {
            return Result.fail("該優惠券不存在,請重繪!");
        }
        //判斷秒殺券是否在有效時間內
        //若不在有效期,則回傳例外結果
        if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
            return Result.fail("秒殺尚未開始!");
        }
        if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
            return Result.fail("秒殺已經結束!");
        }
        //若在有效期,判斷庫存是否充足
        if (voucher.getStock() < 1) {//庫存不足
            return Result.fail("秒殺券庫存不足!");
        }
        //庫存充足,則扣減庫存(操作秒殺券表)
        boolean success = seckillVoucherService.update().setSql("stock = stock -1").eq("voucher_id", voucherId).update();
        if (!success) {//操作失敗
            return Result.fail("秒殺券庫存不足!");
        }
        //扣減庫存成功,則創建訂單,回傳訂單id
        VoucherOrder voucherOrder = new VoucherOrder();
        //設定訂單id
        long orderId = redisIdWorker.nextId("order");
        voucherOrder.setId(orderId);
        //設定用戶id
        Long userId = UserHolder.getUser().getId();
        voucherOrder.setUserId(userId);
        //設定代金券id
        voucherOrder.setVoucherId(voucherId);

        //將訂單寫入資料庫(操作優惠券訂單表)
        this.save(voucherOrder);

        //回傳訂單id
        return Result.ok(orderId);
    }
}

(5)控制器 VoucherOrderController

package com.hmdp.controller;


import com.hmdp.dto.Result;
import com.hmdp.service.IVoucherOrderService;
import com.hmdp.service.IVoucherService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 秒殺券前端控制器
 *
 * @author 李
 * @version 1.0
 */
@RestController
@RequestMapping("/voucher-order")
public class VoucherOrderController {
    @Resource
    private IVoucherOrderService voucherOrderService;

    @PostMapping("seckill/{id}")
    public Result seckillVoucher(@PathVariable("id") Long voucherId) {
        return voucherOrderService.seckillVoucher(voucherId);
    }
}

(6)測驗,在前端頁面點擊購買,顯示搶購成功,訂單號如下:

image-20230424163828781

優惠券訂單表tb_voucher_order成功插入一條資料:

image-20230424164101927

對應的秒殺券的庫存減一:

image-20230424164300622

4.3超賣問題

4.3.1問題分析

4.2的代碼并沒有考慮到并發的問題:當有多個用戶同時對一個秒殺券進行搶購,并發會讓系統出現超賣問題:即賣出的秒殺券數量>實際的秒殺券庫存

我們使用jemeter測驗:

image-20230424165758548 image-20230424165828025 image-20230424170309980

運行上述設定,測驗結果如下:

  1. 秒殺券表中,id=2的秒殺券庫存出現了負數:

    image-20230424170139020
  2. 訂單表中,對應的數量為104單,但是對應的秒殺券的庫存最多只有100張,也就是說:出現了超賣問題

    image-20230424170544754

出現超賣問題的原因:

4.2的代碼只是簡單地進行庫存判斷,并沒有考慮到執行緒并發,當有多個執行緒同時去判斷庫存時,如果當前庫存大于0,則這些執行緒都會去進行庫存扣減,從而發生并發安全問題:

image-20230424171155754 image-20230424171918982

4.3.2解決方案

超賣問題是典型的多執行緒安全問題,針對這一問題的常見解決方案就是加鎖:

image-20230424172233037

這里使用樂觀鎖方案,樂觀鎖的關鍵是判斷之前查詢到的資料是否有被修改過:

常見的方式有兩種:

(1)版本號法:

表中設定一個版本號欄位,執行緒在修改表之前,先查詢一次版本號,對資料庫表操作時,再查詢一次版本號,如果值和之前的一致,說明此時表的資料在兩次查詢之間沒有被修改過,我們就可以進行業務操作,并設定新的版本號,

update陳述句會對當前修改的行進行鎖定操作(資料庫有行級鎖,不用擔心一行記錄被同時修改),

因此,進行表修改時,由于資料庫行鎖,其他執行緒會等待資料修改后再更新庫存

sql執行是交給資料庫的,如果開啟了事務的話,就是兩個事務的并發問題,此時將會啟動兩階段封鎖協議,保證事務并發安全

image-20230424180914306

image-20230424181018721 image-20230424181058145

(2)CAS法:

這里為了簡化,使用庫存代替版本號,原理和方案1是一致的:執行緒在修改表之前,先查詢一次庫存的值,對資料庫表操作時,再查詢一次庫存值,如果值和之前的一致,說明此時表的資料在兩次查詢之間沒有被修改過,我們就可以進行業務操作,

image-20230424183341487

image-20230424183557589 image-20230424183641411

CAS思想:Compare-And-Swap

CAS 有三個運算元:記憶體值 V、預期值 A、要修改的值 B,CAS 最核心的思路就是,僅當預期值 A 和當前的記憶體值 V 相同時,才將記憶體值修改為 B,

ABA問題

為了簡便,這里使用方案2,但實際的業務還是建議使用版本法來避免其他問題,

4.3.3代碼實作

(1)修改VoucherOrderServiceImpl,添加如下代碼:

image-20230424191811284

(2)測驗:

清除之前的訂單資訊(tb_voucher_order):

image-20230424192136997

還原tb_seckill_voucher表的測驗資料:

image-20230424192255563

然后使用jemeter進行測驗:

image-20230424204420148 image-20230424204442421

測驗結果:

券沒有超賣,但是出現了新的問題:前幾個請求中就出現了下單失敗的情況,200個執行緒只有100-63=37個執行緒下單成功(理想情況下是100,即秒殺券全部賣出)

image-20230424204357434

原因分析:這是因為,當有一個執行緒去修改資料時,其他很多的執行緒也來同時請求,它們都根據第一次查詢的stock值去判斷,發現stock值變化了,因此當第一個執行緒修改資料后,都沒有去對資料進行操作),導致發生了庫存充足,仍然搶不到券的情況(搶券失敗率偏高),

(3)改進:修改VoucherOrderServiceImpl,修改如下劃線處:

分析:執行緒A獲取stock值,通過業務判斷,然后去對庫存值進行update操作;因為update陳述句會對當前修改的行進行鎖定操作,因此,進行表修改時,由于資料庫行鎖,其他執行緒會等待資料修改后再更新庫存,當等待后獲取鎖,將where stock > 0作為update條件,這時,只要stock不小于0就仍可以售券,

update where 是先走where去拿鎖,拿不到就阻塞,等拿到鎖了再去執行update

image-20230424205453393

再次對其測驗:可以看到200個執行緒并發,100張秒殺券全部售完,并且沒有出現超賣現象,同時解決了庫存充足卻搶不到券的問題,

image-20230424212235502

4.3.4總結

超賣這樣的執行緒安全問題,解決方案有哪些?

  1. 悲觀鎖:添加同步鎖,讓執行緒串行執行
    • 優點:簡答粗暴
    • 缺點:性能一般
  2. 樂觀鎖:不加鎖,在更新時判斷是否有其他執行緒在修改
    • 優點:性能好
    • 缺點:成功率低

4.4一人一單

4.5分布式鎖

4.6Redis優化秒殺

4.7Redis訊息佇列實作異步秒殺

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/551133.html

標籤:NoSQL

上一篇:SQL優化處理

下一篇:返回列表

標籤雲
其他(158057) Python(38099) JavaScript(25391) Java(17999) C(15217) 區塊鏈(8260) C#(7972) AI(7469) 爪哇(7425) MySQL(7143) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5328) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4559) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2430) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1960) Web開發(1951) HtmlCss(1926) python-3.x(1918) 弹簧靴(1913) C++(1911) xml(1889) PostgreSQL(1873) .NETCore(1855) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day05-優惠券秒殺01

    功能03-優惠券秒殺01 4.功能03-優惠券秒殺 4.1全域唯一ID 4.1.1全域ID生成器 每個店鋪都可以發布優惠券: 當用戶搶購時,就會生成訂單,并保存到tb_voucher_order這張表中。訂單表如果使用資料庫的自增id就存在一些問題: id的規律性太明顯:用戶可以根據id猜測一些資訊 ......

    uj5u.com 2023-04-25 08:31:23 more
  • SQL優化處理

    1、通過慢查日志等定位那些執行效率較低的SQL陳述句 2、explain 分析SQL的執行計劃 需要重點關注type、rows、filtered、extra。 type由上至下,效率越來越高 ALL 全表掃描 index 索引全掃描 range 索引范圍掃描,常用語<,<=,>=,between,in ......

    uj5u.com 2023-04-25 08:30:43 more
  • 2023云資料庫技術沙龍MySQL x ClickHouse專場成功舉辦

    4月22日,2023首屆云資料庫技術沙龍 MySQL x ClickHouse 專場,在杭州市海智中心成功舉辦。本次沙龍由玖章算術、菜根發展、良倉太炎共創聯合主辦。圍繞“技術進化,讓資料更智能”為主題,匯聚位元組跳動、阿里云、玖章算術、華為云、騰訊云、百度的6位資料庫領域專家,深入 MySQL x C... ......

    uj5u.com 2023-04-25 08:30:38 more
  • 資料庫系統概論—標準語言SQL

    資料庫系統概論—基礎篇(2) 三、關系資料庫標準語言SQL 1、資料定義 1.1基本表的定義、洗掉與修改 定義基本表 #建立學生表 CREATE TABLE Student( Sno CHAR(9) PRIMARY KEY, Sname CHAR(20) UNIQUE, Ssex CHAR(2), ......

    uj5u.com 2023-04-25 08:30:33 more
  • 技術干貨|如何利用 ChunJun 實作資料實時同步?

    實時同步是 ChunJun 的?個重要特性,指在資料同步程序中,資料源與?標系統之間的資料傳輸和更新?乎在同?時間進?。 在實時同步場景中我們更加關注源端,當源系統中的資料發?變化時,這些變化會?即傳輸并應?到?標系統,以保證兩個系統中的資料保持?致。這個特性需要作業運?程序中 source 插件不 ......

    uj5u.com 2023-04-25 08:30:11 more
  • 輕松拿下PostgreSQL,這30個實用SQL陳述句你細品

    PostgreSQL是一款功能非常強大的開源關系型資料庫,它支持哈希索引、反向索引、部分索引、Expression 索引、GiST、GIN等多種索引模式,同時可安裝功能豐富的擴展包。相較于Mysql,PostgreSQ支持通過PostGIS擴展支持地理空間資料、支持嵌套回圈,哈希連接,排序合并三種表... ......

    uj5u.com 2023-04-24 09:17:41 more
  • kafka設計理念決議

    一.引言 kafka是廣泛使用的流處理組件,我們知道怎么使用它,也知道它的實作原理。但是更重要的部分是它的設計理念,即kafka設計者當時是如何考量各種方案的,了解這些,對提升我們的設計能力非常有幫助。 二.動機 我們將 Kafka 設計為一個統一平臺,來處理大型公司可能擁有的所有實時資料流。 為此 ......

    uj5u.com 2023-04-24 09:07:02 more
  • oracle邏輯備份exp匯出指定表名時需要加括號嗎?

    Oracle 的exp、imp、expdp、impdp命令用于資料庫邏輯備份與恢復; exp命令用于把資料從遠程資料庫server匯出至本地,生成dmp檔案。 筆者在實操中遇到: $exp user/pass file=exp.dmp tables = (TABLE1,TABLE3,TABLE3) ......

    uj5u.com 2023-04-24 09:01:52 more
  • 讀《mysql是怎樣運行的》有感

    最近讀了一本書《mysql是怎樣運行的》,讀完后在大體上對mysql的運行有一定的了解。在以前,我對mysql有以下的為什么: InnoDB中的表空間、段、區和頁是什么? redo log為什么就能實作事務的持久性? 到底什么是意向鎖?意向鎖有什么用? mysql中的外連接、內連接到底是什么? 事務 ......

    uj5u.com 2023-04-24 09:01:49 more
  • 《Redis設計與實作》讀書筆記

    《Redis設計與實作》讀書筆記 簡單動態字串 SDS的定義 結構: buf陣列:用于保存字串 len屬性:記錄SDS中保存字串的長度 free屬性:記錄buf中未使用位元組數量 遵循C字串以空字串結尾的慣例,保存空字串的位元組不計入長度 SDS與C字串的區別 常數復雜度獲取字串長度 因 ......

    uj5u.com 2023-04-24 09:01:39 more