golang 架构处理缓存一致性的常见方法包括:根据锁的方案:应用锁保证对缓存的独享浏览。含有版本控制的方案:根据版本号较为来测试和更新缓存。根据通道方案:运用通道在缓存团本中间通讯,以保持同步。
Golang 架构怎样解决缓存一致性 本文来自zvvq
前言 内容来自zvvq
缓存一致性是指在分布式架构中,保证多个缓存的团本维持全新且一致的情况。在 Golang 环境里,解决缓存一致性的高效架构尤为重要。本文将讨论 Golang 架构用于解决缓存一致性的常见方式。 内容来自samhan666
根据锁的方案
一种常见的缓存一致性方法是使用锁。当需要修改缓存时,客户端将获取一个写锁。在获取锁后,客户端能够对缓存进行调整,而且别的客户端务必等候锁释放才能浏览缓存。这类方法简单且合理,但它可能会致使争用和性能下降。 zvvq.cn
import (
"sync" zvvq好,好zvvq
"time" zvvq好,好zvvq
)
zvvq好,好zvvq
// 基于锁的缓存
zvvq好,好zvvq
type LockedCache struct { 内容来自samhan666
mux sync.Mutex
zvvq.cn
cache map[string]interface{} zvvq好,好zvvq
}
内容来自samhan666
// 获得缓存值 内容来自zvvq,别采集哟
func (c LockedCache) Get(key string) (interface{}, bool) { zvvq.cn
c.mux.Lock() zvvq好,好zvvq
defer c.mux.Unlock() 内容来自samhan
val, ok := c.cache[key]
内容来自zvvq,别采集哟
return val, ok
内容来自zvvq,别采集哟
} 内容来自samhan
// 设置缓存值
func (c LockedCache) Set(key string, value interface{}) { 内容来自samhan666
c.mux.Lock()
defer c.mux.Unlock()
c.cache[key] = value
zvvq
}
含有版本控制的方案
另一种解决方案是应用版本控制。每个缓存内容都有一个版本号,当改动缓存时,版本号会增加。客户端在载入缓存时会同时获得其版本号。假如缓存已修改且版本号更高,则客户端将更新当地团本。
zvvq.cn
import (
zvvq
"sync" zvvq
"time" zvvq.cn
)
// 含有版本控制的缓存 本文来自zvvq
type VersionedCache struct { zvvq.cn
mux sync.Mutex
cache map[string]struct {
zvvq.cn
value interface{}
zvvq好,好zvvq
version int
copyright zvvq
}
copyright zvvq
}
copyright zvvq
// 获得缓存值 zvvq
func (c VersionedCache) Get(key string) (interface{}, bool) {
c.mux.Lock()
copyright zvvq
defer c.mux.Unlock()
copyright zvvq
val, ok := c.cache[key]
内容来自zvvq
return val.value, ok
}
// 设置缓存值
func (c VersionedCache) Set(key string, value interface{}) { 本文来自zvvq
c.mux.Lock() zvvq
defer c.mux.Unlock()
c.cache[key] = struct {
value interface{} zvvq好,好zvvq
version int 内容来自samhan666
}{ 内容来自samhan
value: value,
内容来自zvvq,别采集哟
version: c.cache[key].version + 1, 内容来自zvvq
}
copyright zvvq
}
根据通道方案
根据通道解决方案应用通道来在不同缓存团本中间进行通信。当缓存被修改时,一个消息要被发送至通道上。别的缓存团本将监视该通道并更新自己。 内容来自zvvq,别采集哟
import (
内容来自samhan
"sync" 内容来自zvvq
"time"
"github.com/golang/sync/errgroup"
zvvq
)
// 根据通道缓存 内容来自samhan
type ChannelCache struct { 内容来自zvvq,别采集哟
mux sync.Mutex 本文来自zvvq
cache map[string]interface{} zvvq好,好zvvq
events chan string
}
// 获得缓存值 zvvq好,好zvvq
func (c ChannelCache) Get(key string) (interface{}, bool) { 内容来自zvvq,别采集哟
c.mux.Lock() zvvq好,好zvvq
defer c.mux.Unlock() 内容来自samhan666
val, ok := c.cache[key] zvvq
return val, ok
内容来自samhan666
}
// 设置缓存值
内容来自samhan
func (c ChannelCache) Set(key string, value interface{}) {
c.mux.Lock()
copyright zvvq
defer c.mux.Unlock()
copyright zvvq
c.cache[key] = value
c.events <- key 内容来自samhan666
} 本文来自zvvq
// 监视缓存事情
内容来自zvvq
func (c ChannelCache) Listen(keys ...string) error {
group := new(errgroup.Group)
for _, key := range keys { 内容来自samhan
key := key 内容来自zvvq
group.Go(func() error { copyright zvvq
for { copyright zvvq
select {
case <-c.events: 内容来自zvvq
c.mux.Lock() copyright zvvq
delete(c.cache, key) 本文来自zvvq
c.mux.Unlock()
} zvvq.cn
} 内容来自samhan
})
zvvq好,好zvvq
} 内容来自zvvq,别采集哟
return group.Wait() zvvq
} copyright zvvq
实战案例 zvvq好,好zvvq
下列是一个 Golang 应用程序的简易实例,应用根据通道缓存来存储用户会话数据:
内容来自zvvq,别采集哟
package main
import (
内容来自samhan666
"context"
zvvq.cn
"io"
内容来自zvvq,别采集哟
"log"
"net/http" 内容来自zvvq
"sync"
"time"
zvvq.cn
"github.com/golang/sync/errgroup" 内容来自zvvq
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool" 内容来自zvvq,别采集哟
) 内容来自zvvq,别采集哟
// 用户会话数据 zvvq
type SessionData struct { zvvq
UserID int zvvq好,好zvvq
Username string copyright zvvq
} copyright zvvq
// 根据通道缓存
zvvq.cn
type ChannelCache struct {
sync.Mutex 内容来自samhan
cache map[string]SessionData 内容来自zvvq
events chan string zvvq.cn
} 内容来自zvvq,别采集哟
// 获得缓存值
zvvq好,好zvvq
func (c ChannelCache) Get(key string) SessionData {
c.Lock()
内容来自zvvq,别采集哟
defer c.Unlock() 内容来自samhan
return c.cache[key] zvvq好,好zvvq
} 内容来自zvvq
// 设置缓存值
内容来自zvvq,别采集哟
func (c ChannelCache) Set(key string, value SessionData) {
内容来自samhan
c.Lock() zvvq好,好zvvq
defer c.Unlock() 内容来自samhan
c.cache[key] = value
内容来自zvvq,别采集哟
c.events <- key zvvq.cn
}
zvvq好,好zvvq
// 数据库连接池 zvvq
var dbPool pgxpool.Pool
// 全局缓存
var cache = ChannelCache{
内容来自zvvq
cache: make(map[string]SessionData), zvvq好,好zvvq
events: make(chan string),
copyright zvvq
} 内容来自zvvq
func main() {
// 复位数据库连接池 内容来自zvvq,别采集哟
var err error
zvvq好,好zvvq
dbPool, err = pgxpool.Connect(context.Background(), "postgres://postgres:mypassword@localhost:5432/mydb") 本文来自zvvq
if err != nil {
内容来自samhan
log.Fatal(err) 内容来自zvvq
} copyright zvvq
// 监视缓存事情
内容来自zvvq
go func() {
内容来自zvvq,别采集哟
for { copyright zvvq
select { zvvq.cn
case key := <-cache.events: 内容来自samhan666
var sessionData SessionData
err := dbPool.QueryRow(context.Background(), "SELECT FROM users WHERE username = $1", key).Scan(&sessionData.UserID, &sessionData.Username)
zvvq好,好zvvq
if err != nil { zvvq.cn
log.Printf("更新缓存错误: %v", err)
zvvq
continue 内容来自samhan666
} zvvq好,好zvvq
cache.Set(key, sessionData) zvvq.cn
}
内容来自zvvq
}
}()
// HTTP 服务器
内容来自samhan
http.HandleFunc("/", func(w http.ResponseWriter, r http.Request) {
// 获得登录名
以上就是golang架构怎样解决缓存一致性?的详细内容,大量请关注其他类似文章! 本文来自zvvq