github.com/GuanceCloud/cliutils@v1.1.21/diskcache/README.md (about) 1 # diskcache 2 3 diskcache 是一种类似 wal 的磁盘缓存,它有如下特性: 4 5 - 支持并行读写 6 - 支持分片大小控制 7 - 支持单条数据大小控制 8 - 支持磁盘大小控制(FIFO) 9 10 限制: 11 12 - 不支持随机读取,只支持按照 FIFO 的顺序来消费数据 13 14 ## 实现算法 15 16 ``` 17 Always put data to this file. 18 | 19 | 20 v 21 data 22 | Rotate: if `data` full, move to tail[data.0000000(n+1)] 23 `-----------------------------------------------------------. 24 | 25 | data.00000000 | data.00000001 | data.00000002 | .... <----` 26 ^ 27 `----------------- Always read from this file(the file with smallest number) 28 ``` 29 30 - 当前正在写入的文件 `data` 不会实时消费,如果最近没有写入(3s),读取操作会将 `data` rotate 一下并消费 31 - 数据从 `data.00000001` 处开始消费(`Get`),如果队列上没有可消费的数据,`Get` 操作将返回 `ErrEOF` 32 - `data` 写满之后,将会在队列尾部追加一个新的文件,并重新创建 `data` 写入 33 34 ## 使用 35 36 以下是基本的使用方式: 37 38 ```golang 39 import "github.com/GuanceCloud/diskcache" 40 41 // Create new cache under /some/path 42 c, err := diskcache.Open(WithPath("/some/path")) 43 44 // Create new cache under /some/path, set batch size to 4MB 45 c, err := diskcache.Open(WithPath("/some/path"), WithBatchSize(4*1024*1024)) 46 47 // Create new cache under /some/path, set cache capacity to 1GB 48 c, err := diskcache.Open(WithPath("/some/path"), WithCapacity(1024*1024*1024)) 49 50 if err != nil { 51 log.Printf(err) 52 return 53 } 54 55 // Put data to 56 data := []byte("my app data...") 57 if err := c.Put(data); err != nil { 58 log.Printf(err) 59 return 60 } 61 62 if err := c.Get(func(x []byte) error { 63 // Do something with the cached data... 64 return nil 65 }); err != nil { 66 log.Printf(err) 67 return 68 } 69 70 // get cache metrics 71 m := c.Metrics() 72 log.Println(m.LineProto()) // get line-protocol format of metrics 73 ``` 74 75 这种方式可以直接以并行的方式来使用,调用方无需针对这里的 diskcache 对象 `c` 做互斥处理。 76 77 ## 通过 ENV 控制缓存 option 78 79 支持通过如下环境变量来覆盖默认的缓存配置: 80 81 | 环境变量 | 描述 | 82 | --- | --- | 83 | ENV_DISKCACHE_BATCH_SIZE | 设置单个磁盘文件大小,单位字节,默认 64MB | 84 | ENV_DISKCACHE_MAX_DATA_SIZE | 限制单次写入的字节大小,避免意料之外的巨量数据写入,单位字节,默认不限制 | 85 | ENV_DISKCACHE_CAPACITY | 限制缓存能使用的磁盘上限,一旦用量超过该限制,老数据将被移除掉。默认不限制 | 86 | ENV_DISKCACHE_NO_SYNC | 禁用磁盘写入的 sync 同步,默认不开启。一旦开启,可能导致磁盘数据丢失问题 | 87 | ENV_DISKCACHE_NO_LOCK | 禁用文件目录夹锁。默认是加锁状态,一旦不加锁,在同一个目录多开(`Open`)可能导致文件混乱 | 88 | ENV_DISKCACHE_NO_POS | 禁用磁盘写入位置记录,默认带有位置记录。一旦不记录,程序重启会导致部分数据重复消费(`Get`) | 89 | ENV_DISKCACHE_NO_FALLBACK_ON_ERROR | 禁用错误回退机制 | 90 91 92 ## Prometheus 指标 93 94 所有指标可选的 label 列表如下: 95 96 | label | 取值 | 说明 | 97 | --- | --- | --- | 98 | no_fallback_on_error | true/false | 是否关闭错误回退(即禁止 Get() 回调失败时,再次读到老的数据) | 99 | no_lock | true/false | 是否关闭加锁功能(即允许一个 cache 目录同时被多次 `Open()`) | 100 | no_pos | true/false | 是否关闭 pos 功能 | 101 | no_sync | true/false | 是否关闭同步写入功能 | 102 | path | cache 所在磁盘目录 | cache 所在磁盘目录 | 103 104 指标列表如下: 105 106 | TYPE | NAME | LABELS | HELP | 107 | --- | --- | --- | --- | 108 | COUNTER | `diskcache_put_bytes_total` | `path` | Cache Put() bytes count | 109 | COUNTER | `diskcache_get_total` | `path` | Cache Get() count | 110 | COUNTER | `diskcache_wakeup_total` | `path` | Wakeup count on sleeping write file | 111 | COUNTER | `diskcache_get_bytes_total` | `path` | Cache Get() bytes count | 112 | GAUGE | `diskcache_capacity` | `path` | Current capacity(in bytes) | 113 | GAUGE | `diskcache_max_data` | `path` | Max data to Put(in bytes), default 0 | 114 | GAUGE | `diskcache_batch_size` | `path` | Data file size(in bytes) | 115 | GAUGE | `diskcache_size` | `path` | Current cache size(in bytes) | 116 | GAUGE | `diskcache_open_time` | `no_fallback_on_error,no_lock,no_pos,no_sync,path` | Current cache Open time in unix timestamp(second) | 117 | GAUGE | `diskcache_last_close_time` | `path` | Current cache last Close time in unix timestamp(second) | 118 | GAUGE | `diskcache_datafiles` | `path` | Current un-readed data files | 119 | SUMMARY | `diskcache_get_latency` | `path` | Get() time cost(micro-second) | 120 | SUMMARY | `diskcache_put_latency` | `path` | Put() time cost(micro-second) | 121 | COUNTER | `diskcache_dropped_bytes_total` | `path` | Dropped bytes during Put() when capacity reached. | 122 | COUNTER | `diskcache_dropped_total` | `path` | Dropped files during Put() when capacity reached. | 123 | COUNTER | `diskcache_rotate_total` | `path` | Cache rotate count, mean file rotate from data to data.0000xxx | 124 | COUNTER | `diskcache_remove_total` | `path` | Removed file count, if some file read EOF, remove it from un-readed list | 125 | COUNTER | `diskcache_put_total` | `path` | Cache Put() count | 126 127 ## 性能估算 128 129 测试环境: 130 131 - Model Name : MacBook Pro 132 - Model Identifier : MacBookPro18,1 133 - Chip : Apple M1 Pro 134 - Total Number of Cores : 10 (8 performance and 2 efficiency) 135 - Memory : 16 GB 136 137 > 详见测试用例 `TestConcurrentPutGetPerf`。 138 139 单次写入的数据量在 100KB ~ 1MB 之间,分别测试单线程写入、多线程写入、多线程读写情况下的性能: 140 141 | 测试情况 | worker | 性能(字节/毫秒) | 142 | --- | --- | --- | 143 | 单线程写入 | 1 | 119708 bytes/ms | 144 | 多线程写入 | 10 | 118920 bytes/ms | 145 | 多线程读写 | 10+10 | 118920 bytes/ms | 146 147 综合下来,不管多线程读写还是单线程读写,其 IO 性能在当前的硬件上能达到 100MB/s 的速度。 148 149 ## TODO 150 151 - [ ] 支持一次 `Get()/Put()` 多个数据,提高加锁的数据吞吐量 152 - [ ] 支持 `Get()` 出错时重试机制(`WithErrorRetry(n)`) 153 - [ ] 可执行程序(*cmd/diskcache*)支持查看已有(可能正在被其它进程占用)diskcache 的存储情况