Golang(GO)通道问题,试图实现(复制)数据库/缓存查询方案

问题描述 投票:0回答:1

因此,我不熟悉通道,等待组,互斥锁等,并试图创建一个应用程序,该应用程序查询结构的一部分以获取数据,如果找到数据,则将其加载到映射中。我基本上是在尝试复制缓存/数据库方案(但是为了便于理解,目前在内存中都有这两种方案。)>

现在,在查询数据时,它既可以从数据库又可以从缓存中查询,我为此设置了一个RWMutex;但是在使用另一个go例程(通过通道)读取存储到缓存或db中的数据时。它从(db go-routine)和(cache go-routine)读取。所以我所做的就是每当我从高速缓存go例程中读取数据时,就耗尽了一个元素的db go路由。


package main

import (
    "fmt"
    "math/rand"
    "strconv"
    "sync"
    "time"
)

type Book struct {
    id   int
    name string
}

var cache = map[int]Book{}
var books []Book
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))

func main() {
    cacheCh := make(chan Book)
    dbCh := make(chan Book)
    wg := &sync.WaitGroup{}
    m := &sync.RWMutex{}
    loadDb()
    for i := 0; i < 10; i++ {
        id := rnd.Intn(10)
        wg.Add(1)
        go func(id int, wg *sync.WaitGroup, m *sync.RWMutex, ch chan<- Book) {
            if find, book := queryCache(id, m); find {
                fmt.Println("Found Book In Cache: ", book)
                ch <- book
            }
            wg.Done()
        }(id, wg, m, cacheCh)
        wg.Add(1)
        go func(id int, wg *sync.WaitGroup, m *sync.RWMutex, ch chan<- Book) {
            if find, book := queryDb(id, m); find {
                ch <- book
            }
            wg.Done()
        }(id, wg, m, dbCh)
        go func(dbCh, cacheCh <-chan Book) {
            var book Book
            select {
            case book = <-cacheCh:
                msg := <-dbCh
                fmt.Println("Drain DbCh From: ", msg, "\nBook From Cache: ", book.name)
            case book = <-dbCh:
                fmt.Println("Book From Database: ", book.name)
            }
        }(dbCh, cacheCh)
    }

    wg.Wait()
}

func queryCache(id int, m *sync.RWMutex) (bool, Book) {
    m.RLock()
    b, ok := cache[id]
    m.RUnlock()
    return ok, b
}
func queryDb(id int, m *sync.RWMutex) (bool, Book) {
    for _, val := range books {
        if val.id == id {
            m.Lock()
            cache[id] = val
            m.Unlock()
            return true, val
        }
    }
    var bnf Book
    return false, bnf

}

func loadDb() {
    var book Book
    for i := 0; i < 10; i++ {
        book.id = i
        book.name = "a" + strconv.Itoa(i)
        books = append(books, book)
    }

}

另外,我知道在这段代码中,即使它在缓存中找到不理想的命中,它也会始终查询数据库。但是,这只是一个测试场景,我优先考虑的是用户以尽可能最快的方式接收详细信息(即,如果缓存中不存在详细信息,则不应等待缓存的响应)在查询数据库之前)。

如果可能,请提供帮助,我对此还很陌生,所以可能有些琐碎。

对不起,谢谢。

因此,我不熟悉通道,等待组,互斥锁等,并试图创建一个应用程序,该应用程序查询结构的一部分以获取数据,如果找到数据,则将其加载到映射中。我基本上是想...

go goroutine
1个回答
0
投票

我看到的问题主要与对事物执行顺序的假设有关:

© www.soinside.com 2019 - 2024. All rights reserved.