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

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

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

先寫一個腳本sql,插入2000個用戶

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個字段,一個是mobile,一個是password,生成了mobile從1到2000,密碼默認(rèn)是123456

然后寫一個單元測試,實現(xiàn)新注冊的2000個用戶登錄,然后獲取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個,則會阻塞
		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信號量,來控制協(xié)程的數(shù)量,經(jīng)過測試,發(fā)現(xiàn)limit,loginNum,影響到最后成功的結(jié)果,這其中的的原理我還暫時沒有想清楚。limit為50,loginNum為2000,會存在服務(wù)端正常返回,但是客戶端報EOF,limit為50,loginNum為500的時候,不會出現(xiàn)EOF問題,那說明limit為50是沒問題的,按照道理說,及時loginNum增大到100000也不會有問題,但是卻出現(xiàn)了問題,后面再解決吧。

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

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

相關(guān)文章

  • golang類型斷言的實現(xiàn)示例

    golang類型斷言的實現(xiàn)示例

    在Go語言中,類型斷言用于從接口類型獲取其具體類型的值,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • 詳解Golang中NewTimer計時器的底層實現(xiàn)原理

    詳解Golang中NewTimer計時器的底層實現(xiàn)原理

    本文將主要介紹一下Go語言中的NewTimer,首先展示基于NewTimer創(chuàng)建的定時器來實現(xiàn)超時控制。接著通過一系列問題的跟進,展示了NewTimer的底層實現(xiàn)原理,需要的可以參考一下
    2023-05-05
  • 分析Go語言接口的設(shè)計原則

    分析Go語言接口的設(shè)計原則

    interface是Go語言的基礎(chǔ)特性之一, 可以理解為對一種類型的規(guī)范或者約束。他跟java、c++不同, Go語言實現(xiàn)接口不需要顯示說明實現(xiàn)了哪個接口, 也沒有繼承或者子類或者implement關(guān)鍵字。只是通過約定的形式, 隱式的實現(xiàn)接口中的方法即可
    2021-06-06
  • golang框架gin的日志處理和zap lumberjack日志使用方式

    golang框架gin的日志處理和zap lumberjack日志使用方式

    這篇文章主要介紹了golang框架gin的日志處理和zap lumberjack日志使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Go語言數(shù)據(jù)結(jié)構(gòu)之單鏈表的實例詳解

    Go語言數(shù)據(jù)結(jié)構(gòu)之單鏈表的實例詳解

    鏈表由一系列結(jié)點(鏈表中每一個元素稱為結(jié)點)組成,結(jié)點可以在運行時動態(tài)生成。本文將通過五個例題帶大家深入了解Go語言中單鏈表的用法,感興趣的可以了解一下
    2022-08-08
  • go實現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例

    go實現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例

    本文主要介紹了go實現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • GoFrame?gredis緩存DoVar及Conn連接對象的自動序列化

    GoFrame?gredis緩存DoVar及Conn連接對象的自動序列化

    這篇文章主要為大家介紹了GoFrame?gredis干貨DoVar?Conn連接對象自動序列化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 深入string理解Golang是怎樣實現(xiàn)的

    深入string理解Golang是怎樣實現(xiàn)的

    這篇文章主要為大家介紹了深入string理解Golang是怎樣實現(xiàn)的原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • 一文帶你了解Golang中reflect反射的常見錯誤

    一文帶你了解Golang中reflect反射的常見錯誤

    go?反射的錯誤大多數(shù)都來自于調(diào)用了一個不適合當(dāng)前類型的方法,?而且,這些錯誤通常是在運行時才會暴露出來,而不是在編譯時,如果我們傳遞的類型在反射代碼中沒有被覆蓋到那么很容易就會?panic。本文就介紹一下使用?go?反射時很大概率會出現(xiàn)的錯誤,需要的可以參考一下
    2023-01-01
  • Go語言設(shè)計實現(xiàn)在任務(wù)欄里提醒你喝水的兔子

    Go語言設(shè)計實現(xiàn)在任務(wù)欄里提醒你喝水的兔子

    這篇文章主要為大家介紹了Go語言設(shè)計實現(xiàn)在任務(wù)欄里提醒你喝水的兔子示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01

最新評論

龙游县| 丰都县| 司法| 阿合奇县| 岳阳县| 长春市| 沙雅县| 康保县| 综艺| 沙雅县| 金乡县| 永平县| 溆浦县| 兴国县| 江孜县| 佳木斯市| 额敏县| 晋城| 福鼎市| 舟曲县| 青铜峡市| 扶绥县| 虎林市| 长垣县| 比如县| 娱乐| 天祝| 英德市| 新丰县| 中西区| 沙河市| 双江| 丹凤县| 大方县| 昌吉市| 东海县| 酉阳| 尚义县| 东兰县| 蒙城县| 阳原县|