golang实现带过期时间的键值对存储插件库timedmap的使用
Golang实现带过期时间的键值对存储插件库timedmap的使用
介绍
timedmap是一个带有过期键值对的map结构,它允许设置在一定时间后自动过期的键值对。当键值对过期时,可以执行回调函数。
安装
go get -u github.com/zekroTJA/timedmap/v2
重要说明
v2版本引入了以下重大变更:
- 需要Go 1.19或更高版本
- TimedMap和构造函数现在使用类型参数以提高类型安全性
- 移除了Sections以提高性能和简化包
- 移除了之前已弃用的函数
使用示例
下面是一个完整的示例代码,展示了如何使用timedmap:
package main
import (
"log"
"time"
"github.com/zekroTJA/timedmap/v2"
)
func main() {
// 创建一个新的timedmap,每隔1秒扫描一次过期的键
tm := timedmap.New[string, int](1 * time.Second)
// 添加一个键"hey",值为213,3秒后过期
// 过期时会执行回调函数,打印过期信息
tm.Set("hey", 213, 3*time.Second, func(v int) {
log.Println("key-value pair of 'hey' has expired")
})
// 打印键"hey"的值
printKeyVal(tm, "hey")
// 等待5秒
// 在此期间主线程被阻塞,"hey"键值对将会过期
time.Sleep(5 * time.Second)
// 再次尝试打印键"hey"的值,此时会失败因为键值对已经过期
printKeyVal(tm, "hey")
}
// 打印指定键的值
func printKeyVal(tm *timedmap.TimedMap[string, int], key string) {
d, ok := tm.GetValue(key)
if !ok {
log.Println("data expired")
return
}
log.Printf("%v = %d\n", key, d)
}
代码说明
- 首先导入必要的包,包括timedmap/v2
- 使用
timedmap.New
创建一个新的TimedMap实例,指定键和值的类型以及扫描间隔 - 使用
Set
方法添加键值对,指定过期时间和过期回调函数 - 使用
GetValue
方法获取键对应的值,返回值和是否存在标志 - 当键值对过期时,回调函数会自动执行
实际应用
timedmap可以用于多种场景,如:
- 缓存系统
- 限流器
- 临时数据存储
这个包已经被用于myrunes.com的REST API限流实现中。
更多关于golang实现带过期时间的键值对存储插件库timedmap的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang实现带过期时间的键值对存储插件库timedmap的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 实现带过期时间的键值对存储 - timedmap 使用指南
在 Go 中实现带过期时间的键值对存储是一个常见需求,下面我将介绍如何使用 timedmap 库来实现这一功能。
timedmap 简介
timedmap 是一个 Go 语言实现的键值存储库,主要特点是:
- 自动处理键值对的过期
- 线程安全
- 提供回调函数支持
- 简单易用的 API
安装
go get github.com/zekroTJA/timedmap
基本使用示例
package main
import (
"fmt"
"time"
"github.com/zekroTJA/timedmap"
)
func main() {
// 创建一个新的 timedmap 实例,设置默认清理间隔为1秒
tm := timedmap.New(1 * time.Second)
// 设置键值对,5秒后过期
tm.Set("key1", "value1", 5*time.Second, nil)
// 获取值
if val, ok := tm.GetValue("key1").(string); ok {
fmt.Println("Got value:", val) // 输出: Got value: value1
}
// 等待6秒后键将自动过期
time.Sleep(6 * time.Second)
if val := tm.GetValue("key1"); val == nil {
fmt.Println("Key expired") // 输出: Key expired
}
}
高级功能
1. 设置过期回调函数
tm.Set("key2", "value2", 3*time.Second, func(value interface{}) {
fmt.Printf("Key 'key2' expired with value: %v\n", value)
})
2. 手动删除键
tm.Remove("key1")
3. 刷新键的过期时间
// 将key1的过期时间重置为10秒后
tm.Refresh("key1", 10*time.Second)
4. 获取剩余生存时间
if ttl := tm.GetExpires("key1"); ttl > 0 {
fmt.Printf("Key will expire in %v\n", ttl)
}
5. 批量操作
// 批量设置
tm.SetMultiple(map[string]interface{}{
"key3": "value3",
"key4": "value4",
}, 5*time.Second)
// 获取所有键
keys := tm.Keys()
fmt.Println("All keys:", keys)
实际应用示例
package main
import (
"fmt"
"time"
"github.com/zekroTJA/timedmap"
)
func main() {
// 创建缓存实例,设置清理间隔为1秒
cache := timedmap.New(1 * time.Second)
// 模拟用户会话存储
cache.Set("user:123", map[string]interface{}{
"name": "Alice",
"email": "alice@example.com",
"token": "abc123xyz",
}, 30*time.Minute, func(value interface{}) {
user := value.(map[string]interface{})
fmt.Printf("User session expired: %s (%s)\n", user["name"], user["email"])
})
// 模拟API请求
go func() {
time.Sleep(5 * time.Second)
if user, ok := cache.GetValue("user:123").(map[string]interface{}); ok {
fmt.Printf("API request from %s\n", user["name"])
// 每次访问后刷新会话
cache.Refresh("user:123", 30*time.Minute)
}
}()
// 保持程序运行
time.Sleep(1 * time.Hour)
}
性能考虑
-
清理间隔 (
New()
函数的参数) 会影响性能:- 间隔越短,过期检测越及时,但CPU使用率越高
- 间隔越长,内存可能短暂保留已过期的键,但CPU使用率低
-
对于高并发场景,timedmap 内部使用读写锁保证线程安全
替代方案
如果需要更高级的功能,也可以考虑:
github.com/patrickmn/go-cache
- 功能更丰富的内存缓存- Redis - 如果需要在多实例间共享缓存
timedmap 是一个轻量级解决方案,适合简单的内存缓存需求,特别是需要精确控制键过期时间的场景。