目录GCache分布式缓存GCacheGCache简介定义:GCache是一个高性能的内存缓存库,用于在Go语言中实现本地缓存功能。特点:高性能支持多种缓存策略简单易用安装GCachegoget-ugithub.com/patrickmn/go-cac
定义:GCache 是一个高性能的内存缓存库,用于在 Go 语言中实现本地缓存功能。
特点:
go get -u github.com/patrickmn/go-cache
package main
import (
"fmt"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置键值对
c.Set("key", "value", cache.DefaultExpiration)
// 获取值
val, found := c.Get("key")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key not found")
}
}
cache.DefaultExpiration
time.Duration
package main
import (
"fmt"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置键值对及过期时间
c.Set("key", "value", 1*time.Minute)
// 等待一段时间
time.Sleep(2 * time.Minute)
// 尝试获取值
val, found := c.Get("key")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key expired or not found")
}
}
c.SetMulti
c.GetMulti
package main
import (
"fmt"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 批量设置键值对
items := map[string]interface{}{
"key1": "value1",
"key2": "value2",
}
c.SetMulti(items, cache.DefaultExpiration)
// 批量获取值
vals, err := c.GetMulti([]string{"key1", "key2"})
if err == nil {
fmt.Println("Values:", vals)
} else {
fmt.Println("Error:", err)
}
}
c.Delete
c.Flush
package main
import (
"fmt"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置键值对
c.Set("key", "value", cache.DefaultExpiration)
// 删除键
c.Delete("key")
// 尝试获取值
val, found := c.Get("key")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key deleted or not found")
}
// 清空所有键
c.Flush()
// 尝试获取值
val, found = c.Get("key")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Cache flushed")
}
}
LRU 算法:当缓存满时,移除最近最少使用的项。
package main
import (
"fmt"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置键值对
c.Set("key1", "value1", cache.DefaultExpiration)
c.Set("key2", "value2", cache.DefaultExpiration)
c.Set("key3", "value3", cache.DefaultExpiration)
// 获取值
val, found := c.Get("key1")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key not found")
}
// 再次设置键值对
c.Set("key4", "value4", cache.DefaultExpiration)
// 尝试获取值
val, found = c.Get("key1")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key removed by LRU")
}
}
LFU 算法:当缓存满时,移除最不常用的项。
package main
import (
"fmt"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置键值对
c.Set("key1", "value1", cache.DefaultExpiration)
c.Set("key2", "value2", cache.DefaultExpiration)
c.Set("key3", "value3", cache.DefaultExpiration)
// 获取值
val, found := c.Get("key1")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key not found")
}
// 再次获取值
val, found = c.Get("key1")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key not found")
}
// 再次设置键值对
c.Set("key4", "value4", cache.DefaultExpiration)
// 尝试获取值
val, found = c.Get("key2")
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key removed by LFU")
}
}
检查错误:if err != nil { ... }
package main
import (
"fmt"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置键值对
err := c.Set("key", "value", cache.DefaultExpiration)
if err != nil {
fmt.Println("Error setting key:", err)
return
}
// 获取值
val, found := c.Get("key")
if !found {
fmt.Println("Key not found")
return
}
fmt.Println("Value:", val)
}
并发安全:GCache 默认是线程安全的。
package main
import (
"fmt"
"sync"
"time"
"github.com/patrickmn/go-cache"
)
func main() {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
var wg sync.WaitGroup
wg.Add(10)
// 并发设置键值对
for i := 0; i < 10; i++ {
go func(i int) {
defer wg.Done()
err := c.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("value%d", i), cache.DefaultExpiration)
if err != nil {
fmt.Println("Error setting key:", err)
return
}
}(i)
}
wg.Wait()
// 获取值
for i := 0; i < 10; i++ {
val, found := c.Get(fmt.Sprintf("key%d", i))
if found {
fmt.Println("Value:", val)
} else {
fmt.Println("Key not found")
}
}
}
使用测试框架:testing
package main
import (
"testing"
"time"
"github.com/patrickmn/go-cache"
)
func TestCache(t *testing.T) {
// 初始化缓存
c := cache.New(5*time.Minute, 10*time.Minute)
// 设置键值对
err := c.Set("key", "value", cache.DefaultExpiration)
if err != nil {
t.Errorf("Failed to set key: %v", err)
}
// 获取值
val, found := c.Get("key")
if !found {
t.Errorf("Key not found")
}
if val != "value" {
t.Errorf("Unexpected value: %v", val)
}
}
定义:分布式缓存是一种存储在多个网络节点上的数据存储方式,旨在提高数据访问速度和系统整体性能。 作用:减少数据库负载,加快数据读取速度。
根据项目需求(如数据持久化需求、数据结构支持等)选择合适的缓存系统。
环境搭建
# 安装 Redis 服务器
sudo apt-get install redis-server
# 安装 go-redis 库
go get -u github.com/go-redis/redis/v8
编写客户端代码
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
func main() {
// 连接 Redis 服务
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
// 设置键值对
ctx := context.Background()
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}
// 获取值
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key:", val) // 输出 "key: value"
}
基本命令:
SET key value
GET key
DEL key
高级命令:
HSET key field value
HGET key field
LPUSH key value
LPOP key
SADD key member
SREM key member
ZADD key score member
ZRANGE key start stop
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
func main() {
// 创建连接池
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 10, // 设置连接池大小
})
// 设置键值对
ctx := context.Background()
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}
// 获取值
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key:", val) // 输出 "key: value"
}
package main
import (
"context"
"fmt"
"time"
"github.com/go-redis/redis/v8"
)
func main() {
// 创建 Redis 客户端
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
// 设置键值对(异步)
ctx := context.Background()
cmd := rdb.Set(ctx, "key", "value", 0)
go func() {
if err := cmd.Err(); err != nil {
fmt.Println("Error setting key:", err)
} else {
fmt.Println("Key set successfully")
}
}()
// 等待一段时间确保异步操作完成
time.Sleep(1 * time.Second)
// 获取值
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key:", val) // 输出 "key: value"
}
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
func main() {
// 创建 Redis 客户端
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
// 批量设置键值对
ctx := context.Background()
pipeline := rdb.Pipeline()
pipeline.Set(ctx, "key1", "value1", 0)
pipeline.Set(ctx, "key2", "value2", 0)
_, err := pipeline.Exec(ctx)
if err != nil {
panic(err)
}
// 批量获取值
vals, err := rdb.MGet(ctx, "key1", "key2").Result()
if err != nil {
panic(err)
}
fmt.Println("vals:", vals) // 输出 "vals: [value1 value2]"
}
package main
import (
"fmt"
"hash/crc32"
"sort"
"strconv"
)
type ConsistentHash struct {
nodes []string
circle map[int]string
}
func NewConsistentHash(nodes []string) *ConsistentHash {
ch := &ConsistentHash{
nodes: nodes,
circle: make(map[int]string),
}
for _, node := range nodes {
for i := 0; i < 100; i++ {
hash := crc32.ChecksumIEEE([]byte(fmt.Sprintf("%s:%d", node, i)))
ch.circle[hash] = node
}
}
return ch
}
func (ch *ConsistentHash) GetNode(key string) string {
hash := crc32.ChecksumIEEE([]byte(key))
keys := make([]int, 0, len(ch.circle))
for k := range ch.circle {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
if k >= hash {
return ch.circle[k]
}
}
return ch.circle[keys[0]]
}
func main() {
nodes := []string{"node1", "node2", "node3"}
ch := NewConsistentHash(nodes)
fmt.Println(ch.GetNode("key1")) // 输出 "node1"
fmt.Println(ch.GetNode("key2")) // 输出 "node2"
fmt.Println(ch.GetNode("key3")) // 输出 "node3"
}
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
func main() {
// 创建 Redis 集群客户端
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{
"localhost:7000",
"localhost:7001",
"localhost:7002",
},
})
// 设置键值对
ctx := context.Background()
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}
// 获取值
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key:", val) // 输出 "key: value"
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!