欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Golang實(shí)現(xiàn)Redis分布式鎖解決秒殺問題

 更新時(shí)間:2023年08月09日 09:18:52   作者:大杯無糖  
這篇文章主要給大家介紹了使用Golang實(shí)現(xiàn)Redis分布式鎖解決秒殺問題,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下

先寫一個(gè)腳本sql,插入2000個(gè)用戶

INSERT INTO sys_users (mobile, password)
SELECT 
    numbers.n AS mobile,
    '$2a$10$zKQfSn/GCcR6MX4nHk3MsOMhJnI0qxN4MFdiufDMH2wzuTaR9G1sq' AS password
FROM 
    (
        SELECT ones.n + tens.n*10 + hundreds.n*100 + thousands.n*1000 + 1 AS n
        FROM 
            (SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) ones
            CROSS JOIN (SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) tens
            CROSS JOIN (SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) hundreds
            CROSS JOIN (SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) thousands
        ORDER BY n
    ) numbers
LIMIT 2000;

登錄是通過2個(gè)字段,一個(gè)是mobile,一個(gè)是password,生成了mobile從1到2000,密碼默認(rèn)是123456

然后寫一個(gè)單元測試,實(shí)現(xiàn)新注冊的2000個(gè)用戶登錄,然后獲取token

package system
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"reflect"
	"runtime"
	"strings"
	"sync"
	"testing"
	"time"
)
var Global_client *http.Client
func GetGlobalClient() {
	client := &http.Client{
		Transport: &http.Transport{
			MaxIdleConns: 20, // 設(shè)置連接池大小為 200
		},
	}
	Global_client = client
}
func TestBaseApi_TokenNext(t *testing.T) {
	var wg sync.WaitGroup
	loginNum := 2000
	GetGlobalClient()
	s := make(chan string, loginNum)
	limit := make(chan int, 20000)
	//go prilimit(limit)
	go Show()
	for i := 1; i <= 2000000; i++ {
		mobile := fmt.Sprintf("%d", i)
		wg.Add(1)
		password := "123456"
		//向通道中發(fā)送值,如果滿了500個(gè),則會(huì)阻塞
		limit <- 1111
		go obtainToken(mobile, password, &wg, limit, s)
	}
	wg.Wait()
	//當(dāng)數(shù)據(jù)都到了通道里面之后,我們可以關(guān)閉通道
	close(s)
	fmt.Println("通道的長度為:",len(s))
	file, err := os.OpenFile("E:\\Go\\goproject\\LearnExam\\sever\\token.txt", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
	defer file.Close()
	for token := range s {
		if token == "" {
			continue
		}
		_, err = file.WriteString(token + "\n")
		if err != nil {
			return
		}
	}
}
func Show() {
	for {
		num := runtime.NumGoroutine()
		fmt.Printf("當(dāng)前程序中的協(xié)程數(shù)量:%d\n", num)
		time.Sleep(1 * time.Second)
	}
}
func AppendStringToFile(filePath string, content string) error {
	file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	defer file.Close()
	_, err = file.WriteString(content + "\n")
	if err != nil {
		return err
	}
	return nil
}
func obtainToken(mobile, password string, wg *sync.WaitGroup, limit chan int, s chan string) {
	defer wg.Done()
	type Body struct {
		Mobile   string `json:"mobile"`
		Password string `json:"password"`
	}
	b := Body{
		mobile, password,
	}
	bodymarshal, err := json.Marshal(&b)
	if err != nil {
		return
	}
	//再處理一下
	reqBody := strings.NewReader(string(bodymarshal))
	req, err := http.NewRequest("POST", "." +
		"", reqBody)
	if err != nil {
		fmt.Printf("Error creating request for user %s: %v\n", mobile, err)
		return
	}
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	resp, err := Global_client.Do(req)
	if err != nil {
		//fmt.Printf("Error sending request for user %s: %v\n", mobile, err)
		fmt.Printf("Error sending request for user %s: %+v\n", mobile, err)
		fmt.Println("反射:", reflect.TypeOf(err))
		fmt.Println("err是EOF,那resp是:",resp)
		return
	}
	//defer func(Body io.ReadCloser) {
	//	err = Body.Close()
	//	if err != nil {
	//
	//	}
	//}(resp.Body)
	body, err := ioutil.ReadAll(resp.Body) //把請求到的body轉(zhuǎn)化成byte[]
	if err != nil {
		return
	}
	type Result struct {
		Code int `json:"code"`
		Data struct {
			Token string `json:"token"`
		} `json:"data"`
	}
	r := Result{}
	err = json.Unmarshal(body, &r)
	if err != nil {
		return
	}
	if r.Code == 0 {
		s <- r.Data.Token
		temp := <-limit
		fmt.Println("通道取值:", temp)
		fmt.Printf("Token obtained for user %s\n", mobile)
	} else {
		fmt.Printf("Failed to obtain token for user %s\n", mobile)
	}
}

我們使用有緩沖的通道和sync.WaitGroup信號(hào)量,來控制協(xié)程的數(shù)量,經(jīng)過測試,發(fā)現(xiàn)limit,loginNum,影響到最后成功的結(jié)果,這其中的的原理我還暫時(shí)沒有想清楚。limit為50,loginNum為2000,會(huì)存在服務(wù)端正常返回,但是客戶端報(bào)EOF,limit為50,loginNum為500的時(shí)候,不會(huì)出現(xiàn)EOF問題,那說明limit為50是沒問題的,按照道理說,及時(shí)loginNum增大到100000也不會(huì)有問題,但是卻出現(xiàn)了問題,后面再解決吧。

現(xiàn)在已經(jīng)拿到了2000個(gè)用戶的token了,我們使用jemter工具來進(jìn)行壓測

到此這篇關(guān)于Golang實(shí)現(xiàn)Redis分布式鎖解決秒殺問題的文章就介紹到這了,更多相關(guān)Golang Redis解決秒殺問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang基礎(chǔ)之字符串與int、int64類型互相轉(zhuǎn)換

    golang基礎(chǔ)之字符串與int、int64類型互相轉(zhuǎn)換

    這篇文章主要給大家介紹了關(guān)于golang基礎(chǔ)之字符串與int、int64類型互相轉(zhuǎn)換的相關(guān)資料,在Go語言中string轉(zhuǎn)int是一項(xiàng)常見的操作,需要的朋友可以參考下
    2023-07-07
  • 淺析Golang中rune類型的使用

    淺析Golang中rune類型的使用

    從golang源碼中看出,rune關(guān)鍵字是int32的別名(-231~231-1),對(duì)比byte(-128~127),可表示的字符更多,本文就來簡單聊聊它的使用方法吧,希望對(duì)大家有所幫助
    2023-05-05
  • Golang中禁止拷貝的實(shí)現(xiàn)代碼

    Golang中禁止拷貝的實(shí)現(xiàn)代碼

    這篇文章主要給大家介紹了關(guān)于Golang中實(shí)現(xiàn)禁止拷貝的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • GO?env環(huán)境變量配置命令使用

    GO?env環(huán)境變量配置命令使用

    這篇文章主要為大家介紹了GO?env環(huán)境變量配置命令使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • go語言工程結(jié)構(gòu)

    go語言工程結(jié)構(gòu)

    這篇文章主要簡單介紹了go語言工程結(jié)構(gòu),對(duì)于我們學(xué)習(xí)go語言很有幫助,需要的朋友可以參考下
    2015-01-01
  • Golang利用自定義模板發(fā)送郵件的方法詳解

    Golang利用自定義模板發(fā)送郵件的方法詳解

    這篇文章主要給大家介紹了關(guān)于Golang利用自定義模板發(fā)送郵件的方法,文中通過示例代碼將實(shí)現(xiàn)的方法介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • 通過示例深度理解Go channel range

    通過示例深度理解Go channel range

    這篇文章主要為大家介紹了Go channel range使用示例深度理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Go語言中的內(nèi)存布局詳解

    Go語言中的內(nèi)存布局詳解

    這篇文章主要給大家介紹了Go語言中的內(nèi)存布局,那么本文中將嘗試解釋Go如何在內(nèi)存中構(gòu)建結(jié)構(gòu)體,以及結(jié)構(gòu)體在字節(jié)和比特位方面是什么樣子。 有需要的朋友們可以參考借鑒,感興趣的朋友們下面來跟著小編一起學(xué)習(xí)學(xué)習(xí)吧。
    2016-11-11
  • Go多線程中數(shù)據(jù)不一致問題的解決方案(sync鎖機(jī)制)

    Go多線程中數(shù)據(jù)不一致問題的解決方案(sync鎖機(jī)制)

    在Go語言的并發(fā)編程中,如何確保多個(gè)goroutine安全地訪問共享資源是一個(gè)關(guān)鍵問題,Go語言提供了sync包,其中包含了多種同步原語,用于解決并發(fā)編程中的同步問題,本文將詳細(xì)介紹sync包中的鎖機(jī)制,需要的朋友可以參考下
    2024-10-10
  • golang基礎(chǔ)之Gocurrency并發(fā)

    golang基礎(chǔ)之Gocurrency并發(fā)

    這篇文章主要介紹了golang基礎(chǔ)之Gocurrency并發(fā),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07

最新評(píng)論