xhash

package
v1.3.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2026 License: MIT, MIT, MIT Imports: 13 Imported by: 0

Documentation

Overview

Example (FreelruMakeHasher)

Example_freelruMakeHasher 展示 freelru 直接创建默认键哈希函数. 同一进程内同一个 hasher 对按 == 相等的键产生相同 uint32 哈希; NaN 不与自身相等, 不保证重复结果一致. 每次创建 hasher 都选择新 seed, 不同实例, 重启后或跨进程不保证相同, 不应持久化结果. freelru 保留其类型检查, 含接口的键类型需要自定义哈希; 普通缓存使用 NewDefault 等构造器即可自动选择 hasher.

package main

import (
	"fmt"

	"github.com/fufuok/freelru"
)

func main() {
	hasher := freelru.MakeHasher[string]()

	fmt.Println(hasher("lru key") == hasher("lru key"))

}
Output:
true
Example (MaphashComparable)

Example_maphashComparable 展示通用容器键直接使用标准库. seed 在容器构造时生成一次; 同一进程内相同 seed 对按 == 相等的键产生相同哈希, 不保证重启或跨进程一致. NaN 不与自身相等, 重复哈希也不保证相同; 接口中的 slice/map/func 等不可比较动态值会 panic.

package main

import (
	"fmt"
	"hash/maphash"
)

func main() {
	seed := maphash.MakeSeed()
	input := "map key"

	h1 := maphash.Comparable(seed, input)
	h2 := maphash.Comparable(seed, input)
	fmt.Println(h1 == h2)

}
Output:
true

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddBytes32

func AddBytes32(h uint32, b []byte) uint32

AddBytes32 用 b 延续稳定的 FNV-1a 32 位哈希. 相同 h 和 b 在重启后和跨进程仍相同.

func AddBytes64

func AddBytes64(h uint64, b []byte) uint64

AddBytes64 用 b 延续稳定的 FNV-1a 64 位哈希. 字节语义与 AddString64 相同, 相同 h 和 b 在重启后和跨进程仍相同, 可用于持久化增量哈希.

func AddString32

func AddString32(h uint32, s string) uint32

AddString32 用 s 延续稳定的 FNV-1a 32 位哈希. 从相同初始 h 开始时, 相同 s 在重启后和跨进程仍相同.

func AddString64

func AddString64(h uint64, s string) uint64

AddString64 用 s 延续稳定的 FNV-1a 64 位哈希. 从相同初始 h 开始时, 相同 s 在重启后和跨进程结果仍相同.

func AddUint32

func AddUint32(h, u uint32) uint32

AddUint32 用 u 的 4 字节大端表示延续稳定的 FNV-1a 哈希. 相同 h 和 u 在重启后和跨进程仍相同; 历史注释中的 8 字节描述不正确, 实际只处理 4 字节.

func AddUint64

func AddUint64(h uint64, u uint64) uint64

AddUint64 用 u 的大端字节延续稳定的 FNV-1a 哈希. 相同 h 和 u 在重启后和跨进程仍相同, 不依赖进程状态或 maphash 种子.

func Hash

func Hash(b []byte, h hash.Hash) []byte

Hash 重置 h, 写入 b 并返回摘要; h 为 nil 时使用 MD5. 输出稳定性由 h 的算法及参数决定; MD5/SHA 等确定性算法对相同输入在重启后和跨进程仍相同. 带随机种子的实现不保证跨实例或跨进程相同; 本函数会修改 h, 不应并发共用同一实例.

Example

ExampleHash 展示显式选择摘要算法以及兼容的 nil 默认值. Hash 会重置传入的 hash.Hash, 因此不能用来延续该实例已有的摘要状态, 也不要并发共享该实例. 使用 SHA-256 等确定性算法时, 相同内容在同一进程, 重启后和跨进程的结果相同. 对任意自定义 hash.Hash, 稳定性由该实例的算法和种子决定; 例如 maphash.Hash 不保证跨进程一致. Hash(b, nil) 使用 MD5, 与 MD5(b) 等价; 新调用方宜显式选算法或使用对应的 Sha256 等助手.

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	input := []byte("12345")
	sum := xhash.Hash(input, sha256.New())
	fmt.Println(hex.EncodeToString(sum) == xhash.Sha256Hex(string(input)))
	fmt.Println(hex.EncodeToString(xhash.Hash(input, nil)) == xhash.MD5BytesHex(input))

}
Output:
true
true

func HashBytes

func HashBytes(b ...[]byte) string

HashBytes 拼接字节并返回 HashBytes64 的稳定十进制形式. 相同字节在重启后和跨进程仍得到相同字符串; 十进制形式用于展示或旧键, 数值调用方应使用 HashBytes64.

func HashBytes32

func HashBytes32(b ...[]byte) uint32

HashBytes32 拼接字节并返回稳定的 FNV-1a 32 位哈希. 相同拼接内容在重启后和跨进程仍得到相同结果; 仅当拼接字节表示相同字符串内容时, 才与 HashString32 一致.

func HashBytes64

func HashBytes64(b ...[]byte) uint64

HashBytes64 拼接字节并返回稳定的 FNV-1a 64 位哈希. 相同拼接内容在重启后和跨进程仍得到相同结果. 拼接不保留各参数边界, 相同字节内容与 HashString64 一致.

func HashSeedString

func HashSeedString(seed maphash.Seed, s string) uint64

HashSeedString 直接返回 maphash.String(seed, s). 相同 seed 和输入在当前进程内结果相同; seed 必须由 maphash.MakeSeed 创建, 零值会 panic. seed 不能跨进程重建, 结果不可作为重启后或跨进程稳定的协议值.

Example

ExampleHashSeedString 展示固定保存一个 maphash.Seed 的进程内用法. HashSeedString 等价于 maphash.String; seed 必须由 maphash.MakeSeed 创建并复用, 零 seed 会 panic. HashSeedUint64 是读取 seed 内部表示的旧整数混合算法, 不等于哈希整数文本或 maphash.Comparable. 两者对各自相同 seed 和输入在同一进程内结果相同, 但不保证重启后或跨进程相同, 不能用于稳定分桶. HashSeedUint64 仅用于兼容现有进程内调用, 新容器的整数键直接使用 maphash.Comparable.

package main

import (
	"fmt"
	"hash/maphash"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	seed := maphash.MakeSeed()
	input := "cache key"

	h1 := xhash.HashSeedString(seed, input)
	h2 := xhash.HashSeedString(seed, input)
	n1 := xhash.HashSeedUint64(seed, 42)
	n2 := xhash.HashSeedUint64(seed, 42)
	fmt.Println(h1 == h2)
	fmt.Println(n1 == n2)

}
Output:
true
true

func HashSeedUint64

func HashSeedUint64(seed maphash.Seed, n uint64) uint64

HashSeedUint64 用进程内 maphash 种子混合 n. 相同 seed 和 n 在当前进程内结果相同, 但重启或其他进程可能不同; 算法也不同于 HashUint64. 该兼容实现读取 maphash.Seed 的内部表示, 不应作为新的稳定哈希接口.

func HashString

func HashString(s ...string) string

HashString 拼接字符串并返回 HashString64 的稳定十进制形式. 相同参数在重启后和跨进程仍得到相同字符串; 现有代理 token 依赖此精确格式, 它不是密码学签名. 参数间不添加分隔符; 需要数值时直接使用 HashString64, 需要区分参数边界时应先明确编码.

Example

ExampleHashString 展示协议使用的十进制字符串包装. HashString 和 HashBytes 对相同拼接内容在同一进程, 重启后和跨进程都得到相同字符串. 它们分别格式化 HashString64 和 HashBytes64 的结果, 数值计算可直接使用后两者. 拼接不加分隔符, 因而 ("12", "345") 与 ("12345") 相同; 需要区分字段边界时应先明确编码.

package main

import (
	"fmt"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	const input = "12345"

	fmt.Println(xhash.HashString(input))
	fmt.Println(xhash.HashBytes([]byte(input)))

}
Output:
16534377278781491704
16534377278781491704

func HashString32

func HashString32(s ...string) uint32

HashString32 拼接字符串并返回稳定的 FNV-1a 32 位哈希. 相同参数拼接后的结果在重启后和跨进程仍相同, 但值域远小于 HashString64. 使用独立的 32 位 FNV 参数, 不是 HashString64 结果的低 32 位.

func HashString64

func HashString64(s ...string) uint64

HashString64 拼接字符串并返回稳定的 FNV-1a 64 位哈希. 相同参数拼接后的结果在重启后和跨进程仍相同, 部署灰度阈值依赖此值. 拼接不添加分隔符, 因此不区分 ("ab", "c") 与 ("a", "bc") 的参数边界.

func HashUint32

func HashUint32(u uint32) uint32

HashUint32 返回 u 的 4 字节大端表示的稳定 FNV-1a 哈希. 相同 u 在重启后和跨进程仍得到相同结果, 不是 runtime memhash.

func HashUint64

func HashUint64(u uint64) uint64

HashUint64 返回 u 的 8 字节大端表示的稳定 FNV-1a 哈希. 相同 u 在重启后和跨进程仍得到相同结果, 不使用进程内 maphash 种子.

func Hmac

func Hmac(b []byte, key []byte, h func() hash.Hash) []byte

Hmac 使用 h 构造带密钥的 MAC, h 为 nil 时使用 MD5. h 应每次返回新的确定性密码学哈希实例; 算法及参数一致时, 相同输入和密钥在重启后及跨进程仍相同. nil 回退是兼容行为, 新调用方应显式传入 sha256.New 等哈希工厂.

func HmacSHA1

func HmacSHA1(b, key []byte) []byte

HmacSHA1 返回稳定的 HMAC-SHA-1 原始值. 相同消息和密钥在重启后和跨进程仍相同, 但 SHA-1 不建议用于新协议.

func HmacSHA1Hex

func HmacSHA1Hex(s, key string) string

HmacSHA1Hex 返回稳定的 HMAC-SHA-1 小写十六进制值. 相同消息和密钥在重启后和跨进程仍相同. 可用于兼容既有校验器, 新代码应使用 HMAC-SHA-256. 对相同消息和密钥, 它是 HmacSHA1 原始结果的小写十六进制表示.

func HmacSHA256

func HmacSHA256(b, key []byte) []byte

HmacSHA256 返回稳定的 HMAC-SHA-256 原始值. 相同消息和密钥在重启后和跨进程仍相同, key 应按密钥保护.

func HmacSHA256Hex

func HmacSHA256Hex(s, key string) string

HmacSHA256Hex 返回稳定的 HMAC-SHA-256 小写十六进制值. 相同消息和密钥在重启后和跨进程仍相同, 不能当作无密钥校验和. 与相同内容的 HmacSHA256 原始结果经十六进制编码后相同, 验证原始 MAC 时应使用 hmac.Equal.

Example

ExampleHmacSHA256Hex 展示带密钥的认证码. HmacSHA256 返回原始字节, HmacSHA256Hex 返回对应的小写十六进制文本. HmacSHA512/HmacSHA512Hex 和 HmacSHA1/HmacSHA1Hex 的原始与文本关系相同, 但算法及输出不同. 这些固定算法对相同消息和密钥在同一进程, 重启后和跨进程都得到相同 MAC, 新协议优先使用 HMAC-SHA-256. Hmac 允许显式传 sha256.New 等密码学哈希工厂, 传 nil 时兼容地使用 MD5; 必须与校验方约定相同算法. HmacSHA1/HmacSHA1Hex 仅用于兼容既有协议; 验证原始 MAC 时应使用 hmac.Equal, 不直接比较文本.

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	const input = "Fufu 中 文加密/解密~&#123a"

	fmt.Println(xhash.HmacSHA256Hex(input, "Fufu"))
	fmt.Println(hex.EncodeToString(xhash.HmacSHA256([]byte(input), []byte("Fufu"))) == xhash.HmacSHA256Hex(input, "Fufu"))
	fmt.Println(hex.EncodeToString(xhash.Hmac([]byte(input), []byte("Fufu"), sha256.New)) == xhash.HmacSHA256Hex(input, "Fufu"))

}
Output:
6d502095be042aab03ac7ae36dd0ca504e54eb72569547dca4e16e5de605ae7c
true
true

func HmacSHA512

func HmacSHA512(b, key []byte) []byte

HmacSHA512 返回稳定的 HMAC-SHA-512 原始值. 相同消息和密钥在重启后和跨进程仍相同. 适用于带密钥的完整性校验, 不适合进程内高频 Map.

func HmacSHA512Hex

func HmacSHA512Hex(s, key string) string

HmacSHA512Hex 返回稳定的 HMAC-SHA-512 小写十六进制值. 相同消息和密钥在重启后和跨进程仍相同. 需要原始字节时使用 HmacSHA512, 不能与 HmacSHA256Hex 的输出直接互换.

func MD5

func MD5(b []byte) []byte

MD5 返回稳定的 MD5 原始摘要. 相同输入在重启后和跨进程仍相同. 这是通用摘要辅助函数, 新代码也可直接调用 md5.Sum.

func MD5BytesHex

func MD5BytesHex(bs []byte) string

MD5BytesHex 返回稳定的 MD5 小写十六进制摘要. 相同字节在重启后和跨进程仍得到相同字符串. nil 和空输入都按空内容处理, 可持久化, 但不应新增安全用途. 需要原始 16 字节时使用 MD5; 相同内容的字符串可使用 MD5Hex, 输出格式一致.

func MD5Hex

func MD5Hex(s string) string

MD5Hex 返回稳定的 MD5 小写十六进制摘要. 相同输入在重启后和跨进程仍得到相同字符串. 现有 token, 签名和 AES 密钥派生依赖此输出; MD5 不抗碰撞, 不应新增安全用途.

Example

ExampleMD5Hex 展示协议使用的 MD5 十六进制输出. MD5Hex 与 MD5BytesHex 对相同内容在同一进程, 重启后和跨进程都相同. MD5 返回原始 16 字节, 经 hex.EncodeToString 后与这两个字符串助手一致. nil 字节切片和空输入都按空内容处理; MD5 仅用于兼容或非安全校验, 不适合新增安全设计.

package main

import (
	"encoding/hex"
	"fmt"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	const input = "12345"

	fmt.Println(xhash.MD5Hex(input))
	fmt.Println(xhash.MD5BytesHex([]byte(input)))
	fmt.Println(hex.EncodeToString(xhash.MD5([]byte(input))) == xhash.MD5Hex(input))

}
Output:
827ccb0eea8a706c4c34a16891f84e7b
827ccb0eea8a706c4c34a16891f84e7b
true

func MD5Reader

func MD5Reader(r io.Reader) (string, error)

MD5Reader 返回从 r 读取的全部字节的稳定 MD5. 相同输入字节在重启后和跨进程仍相同. 非 EOF 读取错误原样返回, 且不返回部分摘要.

Example

ExampleMD5Reader 展示流和文件摘要函数族. MD5Reader 从当前位置读到 EOF, 不负责关闭 r; 相同已读字节在同一进程, 重启后和跨进程的摘要相同. 文件路径可用 MD5Sum(filename), 它负责打开和关闭文件, 读取成功时等价于同内容的 MD5Reader. MD5Sum 遇到目录返回 ("", nil), 打开或读取失败返回错误; 不能只通过 err 判断结果是有效摘要. MustMD5Sum(filename) 忽略 MD5Sum 的错误并返回空字符串, 仅适合允许缺失摘要的场景.

package main

import (
	"fmt"
	"strings"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	sum, err := xhash.MD5Reader(strings.NewReader("12345"))
	if err != nil {
		fmt.Println("read failed:", err)
		return
	}
	fmt.Println(sum)

}
Output:
827ccb0eea8a706c4c34a16891f84e7b

func MD5Sum

func MD5Sum(filename string) (string, error)

MD5Sum 返回文件内容稳定的 MD5 小写十六进制摘要. 相同文件内容在重启后和跨进程仍相同. 目录当前返回空字符串和 nil, 其他状态或读取失败返回错误.

func MemHash

func MemHash(s string) uint64

MemHash 返回进程内 runtime memhash. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同; 不可持久化, 跨进程传输或用于稳定分片. 空字符串按空内容处理; memhash 在长度为零时不会解引用数据指针.

func MemHash32

func MemHash32(s string) uint32

MemHash32 使用 offset32 初始化 runtime memhash 并截断为 32 位, 不保证等于截断 MemHash 的结果. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同; 只能在单个进程内使用, 稳定替代是 Sum32.

func MemHashb

func MemHashb(b []byte) uint64

MemHashb 返回进程内 runtime memhash. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同; 仅适合进程内缓存键. nil 和空切片按空内容处理, 使用公开 unsafe API 直接传递数据指针, 保留原 seed 和算法.

Example

ExampleMemHashb 展示当前进程内缓存键的用法. MemHash 与 MemHashb 分别接收字符串和字节, 同一进程内对相同内容的结果相同; MemHash32 与 MemHashb32 同理. 32 位接口使用不同的初始 seed, 不是截断 MemHash/MemHashb 的 64 位结果; 只能在选择相应宽度时替换. 这些结果不保证重启后或跨进程一致, 不能用作持久化键或稳定分桶; 新代码优先使用固定 seed 的 maphash.

package main

import (
	"fmt"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	input := []byte("request body")
	h1 := xhash.MemHashb(input)
	h2 := xhash.MemHashb(input)

	fmt.Println(h1 == h2)
	fmt.Println(h1 == xhash.MemHash(string(input)))
	fmt.Println(xhash.MemHashb32(input) == xhash.MemHash32(string(input)))

}
Output:
true
true
true

func MemHashb32

func MemHashb32(b []byte) uint32

MemHashb32 使用 offset32 初始化 runtime memhash 并截断为 32 位, 不保证等于截断 MemHashb 的结果. 同一进程内相同输入得到相同值, 但重启或其他进程可能不同, 也不能与 SumBytes32 互换.

func MustMD5Sum

func MustMD5Sum(filename string) string

MustMD5Sum 返回稳定的文件 MD5, 任意错误都返回空字符串. 文件内容相同则重启后和跨进程仍相同. 缺失文件和目录因此无法区分, 需要识别失败时应使用 MD5Sum.

func Sha1

func Sha1(b []byte) []byte

Sha1 返回稳定的 SHA-1 原始摘要. 相同输入在重启后和跨进程仍相同, 但密码学强度不足, 不宜用于新设计.

func Sha1Hex

func Sha1Hex(s string) string

Sha1Hex 返回稳定的 SHA-1 小写十六进制摘要. 相同输入在重启后和跨进程仍相同. 可用于兼容既有协议, 新的完整性校验应使用 SHA-256.

func Sha256

func Sha256(b []byte) []byte

Sha256 返回稳定的 SHA-256 原始摘要. 相同输入在重启后和跨进程仍相同, 可跨进程持久化.

func Sha256Hex

func Sha256Hex(s string) string

Sha256Hex 返回稳定的 SHA-256 小写十六进制摘要. 相同输入在重启后和跨进程仍相同. 适用于内容校验和持久化标识, 不是带密钥的 MAC, 也不适合高频缓存.

Example

ExampleSha256Hex 展示内容校验摘要. Sha256 接受字节并返回原始摘要, Sha256Hex 接受字符串并返回对应的小写十六进制文本. Sha512/Sha512Hex 和 Sha1/Sha1Hex 的原始与文本关系相同, 但算法和摘要长度不同, 不能直接互换结果. 每个算法对相同内容在同一进程, 重启后和跨进程都返回相同摘要; 无密钥摘要不是 MAC. Sha1/Sha1Hex 只用于兼容既有协议, 新的内容校验优先使用 Sha256/Sha256Hex.

package main

import (
	"encoding/hex"
	"fmt"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	const input = "Fufu 中 文加密/解密~&#123a"

	fmt.Println(xhash.Sha256Hex(input))
	fmt.Println(hex.EncodeToString(xhash.Sha256([]byte(input))) == xhash.Sha256Hex(input))

}
Output:
ed3772cefd8991edac6d198df7b62c224b92038e2d435a9a1e2734211e5b5e0b
true

func Sha512

func Sha512(b []byte) []byte

Sha512 返回稳定的 SHA-512 原始摘要. 相同输入在重启后和跨进程仍相同, 与 Go 版本无关.

func Sha512Hex

func Sha512Hex(s string) string

Sha512Hex 返回稳定的 SHA-512 小写十六进制摘要. 相同输入在重启后和跨进程仍相同. 适用于内容完整性校验, 不适合缓存键或高频哈希.

func Sum32

func Sum32(s string) uint32

Sum32 返回稳定的 FNV-1a 32 位哈希. 相同输入在重启后和跨进程仍相同, DataRouter 等持久化路由决策依赖此精确结果.

func Sum64

func Sum64(s string) uint64

Sum64 返回稳定的 FNV-1a 64 位哈希. 相同输入在当前进程, 重启后和其他进程中都得到相同结果, 是 HashString64 的冻结基础算法.

Example

ExampleSum64 展示稳定分桶函数族的相同输入结果. 这些函数不依赖进程随机种子, 相同输入在当前进程, 重启后和其他进程中都相同. Sum64/Sum32 处理字符串, SumBytes64/SumBytes32 对相同字节内容产生对应的相同值. HashString64/HashString32 和 HashBytes64/HashBytes32 先直接拼接参数, 不保留参数边界. AddString64/AddString32 与 AddBytes64/AddBytes32 从给定 h 继续计算, 可替代先拼接再 Sum. HashUint64/HashUint32 与 AddUint64/AddUint32 按固定宽度的大端字节处理整数, 不等于哈希十进制文本. 32 位和 64 位版本使用各自的 FNV 参数, 不能用截断 64 位结果替代 32 位版本.

package main

import (
	"fmt"

	"github.com/fufuok/pkg/xhash"
)

func main() {
	const input = "12345"
	const (
		stableOffset64 uint64 = 14695981039346656037
		stableOffset32 uint32 = 2166136261
	)

	fmt.Println(xhash.Sum64(input))
	fmt.Println(xhash.SumBytes64([]byte(input)))
	fmt.Println(xhash.Sum32(input))
	fmt.Println(xhash.SumBytes32([]byte(input)))
	fmt.Println(xhash.HashString64(input))
	fmt.Println(xhash.HashString32(input))
	fmt.Println(xhash.HashBytes64([]byte(input)))
	fmt.Println(xhash.HashBytes32([]byte(input)))
	fmt.Println(xhash.Sum64(input) == xhash.AddString64(stableOffset64, input))
	fmt.Println(xhash.SumBytes64([]byte(input)) == xhash.AddBytes64(stableOffset64, []byte(input)))
	fmt.Println(xhash.Sum32(input) == xhash.AddString32(stableOffset32, input))
	fmt.Println(xhash.SumBytes32([]byte(input)) == xhash.AddBytes32(stableOffset32, []byte(input)))
	fmt.Println(xhash.HashUint64(1) == xhash.AddUint64(stableOffset64, 1))
	fmt.Println(xhash.HashUint32(1) == xhash.AddUint32(stableOffset32, 1))
	// 固定桶数和编码规则时, 同一键在各进程中落入相同的桶.
	fmt.Println("bucket:", xhash.Sum64(input)%100)
	// 分段计算可以避免为临时拼接分配字符串, 结果与一次性输入相同.
	fmt.Println(xhash.AddString64(xhash.Sum64("12"), "345") == xhash.Sum64(input))

}
Output:
16534377278781491704
16534377278781491704
1136836824
1136836824
16534377278781491704
1136836824
16534377278781491704
1136836824
true
true
true
true
true
true
bucket: 4
true

func SumBytes32

func SumBytes32(bs []byte) uint32

SumBytes32 返回稳定的 FNV-1a 32 位哈希. 相同字节内容与 Sum32 一致, 重启后和跨进程仍相同, 不能替换为 maphash.

func SumBytes64

func SumBytes64(bs []byte) uint64

SumBytes64 返回稳定的 FNV-1a 64 位哈希. 相同字节内容与 Sum64 一致, 重启后和跨进程仍相同, 可用于持久化分桶.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL