// BigCache README 中的简单使用示例
import "github.com/allegro/bigcache"
cache, _ := bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Minute))
cache.Set("my-unique-key", byte("value"))
entry, _ := cache.Get("my-unique-key")
fmt.Println(string(entry))
var map[string]Item
var map[int]int
package main
// newDefaultHasher returns a new 64-bit FNV-1a Hasher which makes no memory allocations.
// Its Sum64 method will lay the value out in big-endian byte order.
// See https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
func newDefaultHasher() fnv64a {
return fnv64a{}
}
type fnv64a struct{}
const (
// offset64 FNVa offset basis. See https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function#FNV-1a_hash
offset64 = 14695981039346656037
// prime64 FNVa prime value. See https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function#FNV-1a_hash
prime64 = 1099511628211
)
// Sum64 gets the string and returns its uint64 hash value.
func (f fnv64a) Sum64(key string) uint64 {
var hash uint64 = offset64
for i := 0; i < len(key); i++ {
hash ^= uint64(key[i])
hash *= prime64
}
return hash
}
[/i]
[i]
hashedkey&mask
0111
AND 1101 (mask)
= 0101
[/i]
[i]
package main
var minShards = 1024
type cache struct {
shards *cacheShard
hash fnv64a
}
func newCache() *cache {
cache := &cache{
hash: newDefaultHasher(),
shards: make(*cacheShard, minShards),
}
for i := 0; i < minShards; i++ {
cache.shards[i] = initNewShard()
}
return cache
}
func (c *cache) getShard(hashedKey uint64) (shard *cacheShard) {
return c.shards[hashedKey&uint64(minShards-1)]
}
func (c *cache) set(key string, value byte) {
hashedKey := c.hash.Sum64(key)
shard := c.getShard(hashedKey)
shard.set(hashedKey, value)
}
func (c *cache) get(key string) (byte, error) {
hashedKey := c.hash.Sum64(key)
shard := c.getShard(hashedKey)
return shard.get(key, hashedKey)
}
[/i][/i]
[i][i]
package main
import (
"encoding/binary"
"errors"
"sync"
)
const (
headerEntrySize = 4
defaultValue = 1024 // For this example we use 1024 like default value.
)
type cacheShard struct {
items map[uint64]uint32
lock sync.RWMutex
array byte
tail int
headerBuffer byte
}
func initNewShard() *cacheShard {
return &cacheShard{
items: make(map[uint64]uint32, defaultValue),
array: make(byte, defaultValue),
tail: 1,
headerBuffer: make(byte, headerEntrySize),
}
}
func (s *cacheShard) set(hashedKey uint64, entry byte) {
w := wrapEntry(entry)
s.lock.Lock()
index := s.push(w)
s.items[hashedKey] = uint32(index)
s.lock.Unlock()
}
func (s *cacheShard) puash(data byte) int {
dataLen := len(data)
index := s.tail
s.save(data, dataLen)
return index
}
func (s *cacheShard) save(data byte, len int) {
// Put in the first 4 bytes the size of the value
binary.LittleEndian.PutUint32(s.headerBuffer, uint32(len))
s.copy(s.headerBuffer, headerEntrySize)
s.copy(data, len)
}
func (s *cacheShard) copy(data byte, len int) {
// Using the tail to keep the order to write in the array
s.tail += copy(s.array[s.tail:], data[:len])
}
func (s *cacheShard) get(key string, hashedKey uint64) (byte, error) {
s.lock.RLock()
itemIndex := int(s.items[hashedKey])
if itemIndex == 0 {
s.lock.RUnlock()
return nil, errors.New("key not found")
}
// Read the first 4 bytes after the index, remember these 4 bytes have the size of the value, so
// you can use this to get the size and get the value in the array using index+blockSize to know until what point
// you need to read
blockSize := int(binary.LittleEndian.Uint32(s.array[itemIndex : itemIndex+headerEntrySize]))
entry := s.array[itemIndex+headerEntrySize : itemIndex+headerEntrySize+blockSize]
s.lock.RUnlock()
return readEntry(entry), nil
}
func readEntry(data byte) byte {
dst := make(byte, len(data))
copy(dst, data)
return dst
}
func wrapEntry(entry byte) byte {
// You can put more information like a timestamp if you want.
blobLength := len(entry)
blob := make(byte, blobLength)
copy(blob, entry)
return blob
}
[/i][/i]
[i][i]
package main
import "fmt"
func main() {
cache := newCache()
cache.set("key", byte("the value"))
value, err := cache.get("key")
if err != nil {
fmt.Println(err)
}
fmt.Println(string(value))
// OUTPUT:
// the value
}
[/i][/i]
本文为 @ 21CTO 创作并授权 21CTO 发布,未经许可,请勿转载。
内容授权事宜请您联系 webmaster@21cto.com或关注 21CTO 公众号。
该文观点仅代表作者本人,21CTO 平台仅提供信息存储空间服务。