【发布时间】:2021-08-11 03:39:06
【问题描述】:
我的应用程序产生了大量的文本数据,为了减少磁盘消耗我想以 gzip 格式写入数据
许多 goroutine 同时调用 WriteData() 函数。
但是 linux gzip 抱怨文件损坏。
zcat ./2021-08-11-00.gz > /dev/null
gzip: ./2021-08-11-00.gz: invalid compressed data--format violated
它不是每次都发生,而是几乎每个第二次写入的文件都发生。
我的代码有什么问题?
我的 DataWrite 包看起来像
package storage
import (
"compress/gzip"
"os"
"sync"
"github.com/rs/zerolog/log"
)
type Storage struct {
handle *os.File
writer *gzip.Writer
lock sync.Mutex
}
func (s *Storage) Init(filename string) error {
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
s.handle = file
s.writer = gzip.NewWriter(file)
return nil
}
func (s *Storage) Shutdown() {
if err := s.writer.Close(); err != nil {
log.Warn().Err(err).Msg("Gzip writer close failed")
}
if err := s.handle.Close(); err != nil {
log.Warn().Err(err).Msg("Gzip handle close failed")
}
}
func (s *Storage) WriteData(data *MyStruct) error {
s.lock.Lock()
defer s.lock.Unlock()
buffer := data.content
_, err := s.writer.Write([]byte(buffer))
if err != nil {
log.Warn().Err(err).Msg("Gzip write failed")
return err
}
if err := s.writer.Flush(); err != nil {
return err
}
if err := s.handle.Sync(); err != nil {
return err
}
return nil
}
【问题讨论】:
-
你可能不应该使用
O_APPEND。我不知道它是否会导致您的问题(我没有看到明显的方法,知道 gzip 编写器是如何工作的),但这也不正确。它有效地使文件不可搜索,并强制所有写入都在末尾。 -
buffer定义在哪里? -
这个程序充满了编译错误。 @AlexBlack 请粘贴一个最小的可重现程序。
-
你应该可以写出一个可复现的例子
-
我已经更新了代码sn-p,