Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一些小修改,缓存,并发安全... #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

xiebaoma
Copy link

1,main.go:当前的 sync 使用了无限循环和 time.Sleep,可能导致 Goroutine 堆积或服务资源浪费。使用 time.Ticker 替代 time.Sleep,并确保任务完成后再开始下一轮。使用标准的日志包或第三方日志库(如 zap 或 logrus),支持日志级别和输出格式化。
2,variable.go:VariablePost 接口未处理记录不存在的情况,直接更新可能会失败
3,cache.go:使用 sync.RWMutex 保证并发安全。RLock 允许多个读操作同时进行,而 Lock 使写操作互斥。增加 cleanup 方法用于删除过期的缓存键,避免缓存占用无效的内存。
4,优化了一些代码,更易扩展和读懂

/*
问题: 当前的 sync 使用了无限循环和 time.Sleep,可能导致 Goroutine 堆积或服务资源浪费。
改进建议: 使用 time.Ticker 替代 time.Sleep,并确保任务完成后再开始下一轮。
*/
func sync() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这样修改似乎并没有本质区别,还是会有goroutine堆积问题,不过其实在实践中因为延时足够长是不需要考虑的,不然直接改成同步也行(?)
另外timeAfter的作用是控制更新范围,如果在延时之后再记录就没有意义了。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

改为同步执行确实好一点,确保每轮同步完成后才进入下一轮,我的想法是将 gorse.Sync 和 search.Sync 由 go 调用改为直接调用
(同步版)
`func sync() {
ticker := time.NewTicker(time.Duration(config.Config.SyncInterval) * time.Second)
defer ticker.Stop()

for range ticker.C {
    // 记录当前时间用于控制更新范围
    timeAfter := time.Now()
    fmt.Println("Syncing... ", timeAfter.Format("2006-01-02 15:04:05"))

    // 同步执行避免潜在的 goroutine 堆积
    if err := gorse.Sync(timeAfter); err != nil {
        fmt.Println("Error syncing gorse:", err)
    }
    if err := search.Sync(timeAfter); err != nil {
        fmt.Println("Error syncing search:", err)
    }
}

}
`

@@ -27,6 +27,7 @@ var Config = struct {
Host string
User string
Password string
Port string // 推荐为字符串形式,例如 "25" 或 "587"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

还需要同步修改config_example.yml


全局 Instance 变量通过工厂方法生成,更加直观。

在 Get 方法中增加判断并调用 cleanup,即使过期键未被主动访问也能正确清理。
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

似乎没找到“未被主动访问也能正常清理”的代码

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我增加了 startCleanup 方法,使用 time.Ticker 定时检查并清理过期缓存
增加了 Stop 方法,用于停止后台清理任务,防止程序退出时遗留 goroutine
这种实现既能满足缓存访问需求,又能保证未被访问的过期数据及时清理,内存使用更加高效。
fix.md

c.JSON(500, gin.H{"msg": "数据库错误Orz"})
// 查询第一条记录
if err := database.DB.Where("obj = ?", query.Obj).First(&variable).Error; err != nil {
if err.Error() == "record not found" {
Copy link
Collaborator

@flwfdd flwfdd Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

理论上有limit的find性能可能比first还好些?如果要用first的话这里err是否用常量而非字符串形式好些

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants