【发布时间】:2020-05-03 20:24:46
【问题描述】:
我有一个 json 文件,其中有数千条记录作为键值对,我通过将其解组为接口来读取这些记录。
var devices map[string]interface{} //globalscope in app
jsonFast:= jsoniter.ConfigFastest
_, b, _, _ := runtime.Caller(0)
dir := filepath.Dir(b)
jsonFile, _ := ioutil.ReadFile(dir + "/devices.json")
_ = jsonFast.Unmarshal(jsonFile, &devices)
这在高负载下的应用程序过程中被多个 goroutine 访问。
现在由于该文件每 5 分钟更新一次,因此在不重新启动应用程序的情况下,我想使该地图界面 devices 无效,以便从文件中加载新数据。
在 node.js 中,我曾经使用 delete require.cache[require.resolve("filename")],但不确定如何在 go 中完成。
我尝试在 SetInterval func(节点版本的端口)中使用互斥锁,我从 here 使用,它每 5 分钟读取一次文件,但我收到此错误:
goroutine 871895 [IO wait]: 这似乎意味着 goroutine 正在等待解锁以从全局变量中读取。
代码:
var m sync.Mutex
//this function execute every 5 minute to read file and reassign to map interface.
_ = setInterval(func() {
jsonFile, _ := ioutil.ReadFile(dir + "/devices.json")
m.Lock() // used this mutex as the step may cause race condition.
_ = jsonFast.Unmarshal(jsonFile, &devices)
m.Unlock()
}, 5* 60 * 1000, false)
//this initializes at the start after which the set interval execute every 5 minute to get updated data.
jsonFile, _ := ioutil.ReadFile(dir + "/devices.json")
_ = jsonFast.Unmarshal(jsonFile, &devices)
我应该采取什么方法来实现这一点?或者有什么方法可以从文件中读取/更新而不是使用映射接口以避免竞争条件和 IO 锁定?
【问题讨论】:
-
goroutine 871895 [IO wait]不是错误,那是 goroutine 的状态。错误应该在转储的开头。请包括实际错误。 -
确保地图访问更安全的一种方法是将整个地图包装在
sync.RWMutex中,但这需要在读取/写入之前锁定整个地图。如果您的 JSON 具有已知结构,您很可能应该将其解组为一个结构,然后将结构的每个部分包装在一个互斥体中。 -
@JohnOss,代码目前已经锁定了地图。当替换整个结构时,这种细粒度的方法会完成什么?当前代码的问题在于,除非所有读取都使用相同的互斥体完成,否则它是不合理的。但让我们先看看这个错误。
-
使用 jsoniter 可能是明智的,但为什么要在 ioutil.ReadFile 之后使用它呢?过早的优化?
标签: go