zvvq技术分享网

golang框架如何解决缓存一致性?(golang cache)

作者:zvvq博客网
导读golang 框架解决缓存一致性的常见方法包括:基于锁的方案:使用锁确保对缓存的独占访问。带有版本控制的方案:通过版本号比较来检测和更新缓存。基于通道的方案:利用通道在缓存

golang 架构处理缓存一致性的常见方法包括:根据锁的方案:应用锁保证对缓存的独享浏览。含有版本控制的方案:根据版本号较为来测试和更新缓存。根据通道方案:运用通道在缓存团本中间通讯,以保持同步。

内容来自zvvq,别采集哟

内容来自zvvq,别采集哟

Golang 架构怎样解决缓存一致性 本文来自zvvq

前言 内容来自zvvq

缓存一致性是指在分布式架构中,保证多个缓存的团本维持全新且一致的情况。在 Golang 环境里,解决缓存一致性的高效架构尤为重要。本文将讨论 Golang 架构用于解决缓存一致性的常见方式。 内容来自samhan666

根据锁的方案

本文来自zvvq

一种常见的缓存一致性方法是使用锁。当需要修改缓存时,客户端将获取一个写锁。在获取锁后,客户端能够对缓存进行调整,而且别的客户端务必等候锁释放才能浏览缓存。这类方法简单且合理,但它可能会致使争用和性能下降。 zvvq.cn

import (

copyright zvvq

"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

// 设置缓存值

本文来自zvvq

func (c LockedCache) Set(key string, value interface{}) { 内容来自samhan666

c.mux.Lock()

zvvq

defer c.mux.Unlock()

内容来自zvvq,别采集哟

c.cache[key] = value

zvvq

}

zvvq好,好zvvq

含有版本控制的方案

zvvq.cn

另一种解决方案是应用版本控制。每个缓存内容都有一个版本号,当改动缓存时,版本号会增加。客户端在载入缓存时会同时获得其版本号。假如缓存已修改且版本号更高,则客户端将更新当地团本。

zvvq.cn

import (

zvvq

"sync" zvvq

"time" zvvq.cn

)

内容来自zvvq

// 含有版本控制的缓存 本文来自zvvq

type VersionedCache struct { zvvq.cn

mux sync.Mutex

zvvq.cn

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) {

copyright zvvq

c.mux.Lock()

copyright zvvq

defer c.mux.Unlock()

copyright zvvq

val, ok := c.cache[key]

内容来自zvvq

return val.value, ok

本文来自zvvq

}

内容来自zvvq,别采集哟

// 设置缓存值

内容来自zvvq

func (c VersionedCache) Set(key string, value interface{}) { 本文来自zvvq

c.mux.Lock() zvvq

defer c.mux.Unlock()

内容来自zvvq,别采集哟

c.cache[key] = struct {

内容来自zvvq,别采集哟

value interface{} zvvq好,好zvvq

version int 内容来自samhan666

}{ 内容来自samhan

value: value,

内容来自zvvq,别采集哟

version: c.cache[key].version + 1, 内容来自zvvq

}

copyright zvvq

}

内容来自zvvq,别采集哟

根据通道方案

zvvq.cn

根据通道解决方案应用通道来在不同缓存团本中间进行通信。当缓存被修改时,一个消息要被发送至通道上。别的缓存团本将监视该通道并更新自己。 内容来自zvvq,别采集哟

import (

内容来自samhan

"sync" 内容来自zvvq

"time"

内容来自samhan

"github.com/golang/sync/errgroup"

zvvq

)

copyright zvvq

// 根据通道缓存 内容来自samhan

type ChannelCache struct { 内容来自zvvq,别采集哟

mux sync.Mutex 本文来自zvvq

cache map[string]interface{} zvvq好,好zvvq

events chan string

内容来自zvvq

}

zvvq好,好zvvq

// 获得缓存值 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

}

zvvq.cn

// 设置缓存值

内容来自samhan

func (c ChannelCache) Set(key string, value interface{}) {

内容来自samhan666

c.mux.Lock()

copyright zvvq

defer c.mux.Unlock()

copyright zvvq

c.cache[key] = value

内容来自zvvq

c.events <- key 内容来自samhan666

} 本文来自zvvq

// 监视缓存事情

内容来自zvvq

func (c ChannelCache) Listen(keys ...string) error {

内容来自samhan666

group := new(errgroup.Group)

copyright zvvq

for _, key := range keys { 内容来自samhan

key := key 内容来自zvvq

group.Go(func() error { copyright zvvq

for { copyright zvvq

select {

copyright zvvq

case <-c.events: 内容来自zvvq

c.mux.Lock() copyright zvvq

delete(c.cache, key) 本文来自zvvq

c.mux.Unlock()

内容来自zvvq,别采集哟

} zvvq.cn

} 内容来自samhan

})

zvvq好,好zvvq

} 内容来自zvvq,别采集哟

return group.Wait() zvvq

} copyright zvvq

实战案例 zvvq好,好zvvq

下列是一个 Golang 应用程序的简易实例,应用根据通道缓存来存储用户会话数据:

内容来自zvvq,别采集哟

package main

zvvq好,好zvvq

import (

内容来自samhan666

"context"

zvvq.cn

"io"

内容来自zvvq,别采集哟

"log"

本文来自zvvq

"net/http" 内容来自zvvq

"sync"

内容来自samhan666

"time"

zvvq.cn

"github.com/golang/sync/errgroup" 内容来自zvvq

"github.com/jackc/pgx/v4"

内容来自zvvq

"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 {

内容来自samhan666

sync.Mutex 内容来自samhan

cache map[string]SessionData 内容来自zvvq

events chan string zvvq.cn

} 内容来自zvvq,别采集哟

// 获得缓存值

zvvq好,好zvvq

func (c ChannelCache) Get(key string) SessionData {

内容来自zvvq

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

内容来自zvvq

// 全局缓存

zvvq

var cache = ChannelCache{

内容来自zvvq

cache: make(map[string]SessionData), zvvq好,好zvvq

events: make(chan string),

copyright zvvq

} 内容来自zvvq

func main() {

本文来自zvvq

// 复位数据库连接池 内容来自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

内容来自samhan

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

}

内容来自samhan

}()

zvvq好,好zvvq

// HTTP 服务器

内容来自samhan

http.HandleFunc("/", func(w http.ResponseWriter, r http.Request) {

内容来自zvvq,别采集哟

// 获得登录名

内容来自samhan

以上就是golang架构怎样解决缓存一致性?的详细内容,大量请关注其他类似文章! 本文来自zvvq