add flush 操作

This commit is contained in:
kingecg 2025-02-23 19:55:04 +08:00
parent bcf7eac85f
commit 8e464964d9
2 changed files with 123 additions and 1 deletions

64
Readme.md Normal file
View File

@ -0,0 +1,64 @@
### README 文档
#### 项目名称gocache
#### 简介
`gocache` 是一个简单的内存键值存储系统,支持持久化、事务处理和内存限制功能。它提供了基本的 `Put`、`Get` 和 `Delete` 操作,并且可以通过日志文件进行恢复。此外,还支持事务处理,确保数据的一致性和可靠性。
#### 目录结构
```
gocache/
├── kvstore.go # 主要实现代码
└── kvstore_test.go # 测试代码
```
#### 安装与使用
1. **安装依赖**
本项目仅依赖 Go 标准库,无需额外安装第三方库。
`go get git.pyer.club/kingecg/gocache`
#### 功能说明
- **KVStore 结构体**
- `NewKVStore(file string, memoryLimit int64, bucketCount int) *KVStore`: 创建一个新的 KVStore 实例。
- `Put(key, value string)`: 添加或更新键值对。
- `Get(key string) (string, bool)`: 获取指定键的值。
- `Delete(key string)`: 删除指定键的键值对。
- `SaveToFile() error`: 将当前存储的数据保存到文件中。
- `LoadFromFile(keys ...string) error`: 从文件加载数据,支持部分加载。
- `BeginTransaction()`: 开始一个新的事务。
- `Commit() error`: 提交当前事务。
- `Rollback()`: 回滚当前事务。
- `PutInTransaction(key, value string)`: 在当前事务中添加或更新键值对。
- `LogOperation(op string, key, value string) error`: 记录操作日志。
- `RecoverFromLog() error`: 从日志文件恢复数据。
- `periodicSave()`: 定时保存脏数据并清空日志文件。
#### 测试用例说明
- **TestNewKVStore**: 测试创建新的 KVStore 实例是否成功。
- **TestPutAndGet**: 测试 `Put``Get` 操作是否正确。
- **TestDelete**: 测试 `Delete` 操作是否能正确删除键值对。
- **TestSaveAndLoadFromFile**: 测试将数据保存到文件并从文件加载的功能。
- **TestLogOperation**: 测试日志记录功能。
- **TestTransaction**: 测试事务处理功能,包括提交和回滚。
#### 注意事项
- **内存限制**`memoryLimit` 参数用于限制内存使用量,当超过限制时会触发 panic。可以根据实际需求调整该参数。
- **持久化**:数据会定期保存到文件中,并且可以通过日志文件进行恢复。请确保有足够的磁盘空间来存储这些文件。
- **事务处理**:事务可以保证一组操作的原子性,但在高并发场景下需要注意锁机制的影响。
#### 贡献指南
欢迎任何开发者为本项目贡献代码或提出改进建议。请遵循以下步骤:
1. Fork 本仓库。
2. 创建新分支 (`git checkout -b feature/your-feature`)。
3. 提交更改 (`git commit -am 'Add some feature'`)。
4. 推送到远程分支 (`git push origin feature/your-feature`)。
5. 提交 Pull Request。
#### 许可证
本项目采用 MIT 许可证,详情请参见 [LICENSE](LICENSE) 文件。
---
希望这份 README 文档能够帮助您更好地理解和使用 `gocache`。如果有任何问题或建议,请随时联系开发者。

View File

@ -112,15 +112,54 @@ func hashKey(key string) int {
return hash
}
// Flush saves dirty keys to file and clears the memory
func (k *KVStore) Flush() error {
k.mu.Lock()
defer k.mu.Unlock()
if len(k.dirtyKeys) == 0 {
return nil
}
// 保存变化到文件
for key := range k.dirtyKeys {
if err := k.saveKeyToBucket(key); err != nil {
return err
}
}
// 清空dirtyKeys
k.dirtyKeys = make(map[string]bool)
// 清空日志文件
if err := os.Truncate(k.logFile, 0); err != nil {
return err
}
// 清空内存
k.store = make(map[string]string)
k.memoryUsage = 0
return nil
}
// Put adds a key/value pair to the store.
func (k *KVStore) Put(key, value string) {
k.mu.Lock()
defer k.mu.Unlock()
// 如果处于事务中,不检查内存限制
if k.transaction != nil {
k.transaction.store[key] = value
return
}
// 检查内存使用量
newMemoryUsage := k.memoryUsage + int64(len(key)+len(value))
if newMemoryUsage > k.memoryLimit {
panic("Memory limit exceeded")
if err := k.Flush(); err != nil {
panic("Failed to flush store")
}
newMemoryUsage = int64(len(key) + len(value))
}
k.store[key] = value
@ -181,10 +220,29 @@ func (k *KVStore) Commit() error {
return nil
}
// 计算事务中键值对的内存使用量
var transactionMemoryUsage int64
for key, value := range k.transaction.store {
transactionMemoryUsage += int64(len(key) + len(value))
}
// 检查内存使用量
newMemoryUsage := k.memoryUsage + transactionMemoryUsage
if newMemoryUsage > k.memoryLimit {
if err := k.Flush(); err != nil {
return err
}
newMemoryUsage = transactionMemoryUsage
}
// 提交事务
for key, value := range k.transaction.store {
k.store[key] = value
k.dirtyKeys[key] = true
}
k.memoryUsage = newMemoryUsage
k.transaction = nil
return nil
}