Documentation ¶
Overview ¶
Example (CacheAsidePattern) ¶
Example_cacheAsidePattern demonstrates multi-layered caching and multiple prefix keys at the same time.
tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheF := cache.NewFactory(rds, tinyLfu) c := cacheF.NewCache([]cache.Setting{ { Prefix: "teacher", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, MarshalFunc: msgpack.Marshal, UnmarshalFunc: msgpack.Unmarshal, }, { Prefix: "student", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, MGetter: func(keys ...string) (interface{}, error) { // The MGetter is used to generate data when cache missed, and refill the cache automatically.. // You can read from DB or other microservices. // Assume we read from MySQL according to the key "jacky" and get the value of // Person{FirstName: "jacky", LastName: "Lin", Age: 38} // HINT: remember to return as a slice, and the item order needs to consist with the keys in the parameters. if len(keys) == 1 && keys[0] == "jacky" { return []Person{{FirstName: "Jacky", LastName: "Lin", Age: 38}}, nil } return nil, fmt.Errorf("XD") }, MarshalFunc: cache.Marshal, UnmarshalFunc: cache.Unmarshal, }, }) ctx := context.TODO() teacher := &Person{} if err := c.GetByFunc(ctx, "teacher", "jacky", teacher, func() (interface{}, error) { // The getter is used to generate data when cache missed, and refill the cache automatically.. // You can read from DB or other microservices. // Assume we read from MySQL according to the key "jacky" and get the value of // Person{FirstName: "jacky", LastName: "Wang", Age: 83} . return Person{FirstName: "Jacky", LastName: "Wang", Age: 83}, nil }); err != nil { panic("not expected") } fmt.Println(teacher) // {FirstName: "Jacky", LastName: "Wang", Age: 83} student := &Person{} if err := c.Get(ctx, "student", "jacky", student); err != nil { panic("not expected") } fmt.Println(student) // {FirstName: "Jacky", LastName: "Lin", Age: 38}
Output: &{Jacky Wang 83} &{Jacky Lin 38}
Example (PubsubPattern) ¶
Example_pubsubPattern demonstrates how to leverage Pubsub pattern to broadcast evictions between distributed systems, and make in-memory cache consistency eventually ASAP.
tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheF := cache.NewFactory(rds, tinyLfu, cache.WithPubSub(rds)) c := cacheF.NewCache([]cache.Setting{ { Prefix: "user", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, }, }) ctx := context.TODO() user := &Person{} if err := c.GetByFunc(ctx, "user", "tony", user, func() (interface{}, error) { // The getter is used to generate data when cache missed, and refill the cache automatically. // Assume we read from MySQL according to the key "tony" and get the value of // Person{FirstName: "Tony", LastName: "Stock", Age: 87} . // At the same time, it will broadcast the eviction about the prefix "user" and the key "tony" to others. return Person{FirstName: "Tony", LastName: "Stock", Age: 87}, nil }); err != nil { panic("not expected") } fmt.Println(user) // {FirstName: "Tony", LastName: "Stock", Age: 87}
Output: &{Tony Stock 87}
Example (SetAndGetPattern) ¶
package main import ( "context" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) type Object struct { Str string Num int } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheF := cache.NewFactory(rds, tinyLfu) // We create a group of cache named "set-and-get". // It uses the shared cache only with TTL of ten seconds. c := cacheF.NewCache([]cache.Setting{ { Prefix: "set-and-get", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: 10 * time.Second}, }, }, }) ctx := context.TODO() // set the cache obj := &Object{ Str: "value1", Num: 1, } if err := c.Set(ctx, "set-and-get", "key", obj); err != nil { panic("not expected") } // read the cache container := &Object{} if err := c.Get(ctx, "set-and-get", "key", container); err != nil { panic("not expected") } fmt.Println(container) // Object{ Str: "value1", Num: 1} // read the cache but failed if err := c.Get(ctx, "set-and-get", "no-such-key", container); err != nil { fmt.Println(err) // errors.New("cache key is missing") } }
Output: &{value1 1} cache key is missing
Index ¶
- Constants
- Variables
- func ClearPrefix()
- func Marshal(value interface{}) ([]byte, error)
- func ParseeventType(name string) (eventType, error)
- func Register(packageKey string)
- func Unmarshal(b []byte, value interface{}) error
- type Adapter
- type Attribute
- type Cache
- type Factory
- type FactoryOptions
- func OnCacheHitFunc(f func(prefix string, key string, count int)) FactoryOptions
- func OnCacheMissFunc(f func(prefix string, key string, count int)) FactoryOptions
- func OnLocalCacheCostAddFunc(f func(prefix string, key string, cost int)) FactoryOptions
- func OnLocalCacheCostEvictFunc(f func(prefix string, key string, cost int)) FactoryOptions
- func WithMarshalFunc(f MarshalFunc) FactoryOptions
- func WithPubSub(pb Pubsub) FactoryOptions
- func WithUnmarshalFunc(f UnmarshalFunc) FactoryOptions
- type MGetterFunc
- type MSetOptions
- type MarshalFunc
- type Message
- type OneTimeGetterFunc
- type Pubsub
- type Redis
- type Result
- type Setting
- type TinyLFUOptions
- type Type
- type UnmarshalFunc
- type Value
Examples ¶
Constants ¶
const ( // EventTypeNone is a eventType of type None. // Not registered Event by default. EventTypeNone eventType = iota // EventTypeEvict is a eventType of type Evict. // Evict presents eviction event. EventTypeEvict )
Variables ¶
var ( // ErrCacheMiss indicates the key is missing ErrCacheMiss = errors.New("cache key is missing") // ErrPfxNotRegistered means the prefix is not registered ErrPfxNotRegistered = errors.New("prefix not registered") // ErrMGetterResponseLengthInvalid means mgetter return a slice with wrong length, // the response length should be equal to the getterParams length ErrMGetterResponseLengthInvalid = errors.New("wrong mgetter response length") // ErrMGetterResponseNotSlice means mgetter's response type is not slice ErrMGetterResponseNotSlice = errors.New("mgetter response not a slice") // ErrResultIndexInvalid means the index for Result.Get is out of range ErrResultIndexInvalid = errors.New("index out of range") )
Functions ¶
func ClearPrefix ¶
func ClearPrefix()
ClearPrefix is only used by unit tests that clean up registered prefix, otherwise duplicated prefix registration panic might occur due to multiple tests.
func ParseeventType ¶ added in v1.1.3
ParseeventType attempts to convert a string to a eventType.
Types ¶
type Adapter ¶
type Adapter interface { MGet(context context.Context, keys []string) ([]Value, error) MSet(context context.Context, keyVals map[string][]byte, ttl time.Duration, options ...MSetOptions) error Del(context context.Context, keys ...string) error }
Adapter is the interface communicating with shared/local caches.
func NewTinyLFU ¶
func NewTinyLFU(size int, options ...TinyLFUOptions) Adapter
NewTinyLFU generates Adapter with tinylfu
type Attribute ¶
Attribute specified details. For example, you need to indicate the TTL for each key to expire.
type Cache ¶
type Cache interface { // GetByFunc returns a value in the cache. It also follows up the Cache-Aside pattern. // When cache-miss happened, it relaods the value by the getter, and fill in the cache again. GetByFunc(context context.Context, prefix, key string, container interface{}, getter OneTimeGetterFunc) error // Get returns a value in the cache. // When cache-miss happened, it relaods the value by MGetter specified in the setting if possible. // Or returns the error of ErrCacheMiss. Get(context context.Context, prefix, key string, container interface{}) error // MGet returns values in the cache with the interface Result. // When cache-miss happened, it relaods values by MGetter specified in the setting if possible. // Or returns the error of ErrCacheMiss. MGet(context context.Context, prefix string, keys ...string) (Result, error) // Del remove keys in the cache Del(context context.Context, prefix string, keys ...string) error // Set sets up a value into the cache. Set(context context.Context, prefix string, key string, value interface{}) error // MSet sets up values into the cache. MSet(context context.Context, prefix string, keyValues map[string]interface{}) error }
Cache is generated by Factory based on the need specified in the Setting slice. Use the following methods to create key/value store.
type Factory ¶
Factory is initialized in the main.go, and used to generate the Cache for each business logic
func NewFactory ¶
func NewFactory(sharedCache Adapter, localCache Adapter, options ...FactoryOptions) Factory
NewFactory returns the Factory initialized in the main.go.
type FactoryOptions ¶ added in v1.1.4
type FactoryOptions func(opts *factoryOptions)
FactoryOptions is an alias for functional argument.
func OnCacheHitFunc ¶
func OnCacheHitFunc(f func(prefix string, key string, count int)) FactoryOptions
OnCacheHitFunc sets up the callback function on cache hitted
func OnCacheMissFunc ¶
func OnCacheMissFunc(f func(prefix string, key string, count int)) FactoryOptions
OnCacheMissFunc sets up the callback function on cache missed
func OnLocalCacheCostAddFunc ¶
func OnLocalCacheCostAddFunc(f func(prefix string, key string, cost int)) FactoryOptions
OnLocalCacheCostAddFunc sets up the callback function on adding the cost of key in local cache
func OnLocalCacheCostEvictFunc ¶
func OnLocalCacheCostEvictFunc(f func(prefix string, key string, cost int)) FactoryOptions
OnLocalCacheCostEvictFunc sets up the callback function on evicting the cost of key in local cache
func WithMarshalFunc ¶
func WithMarshalFunc(f MarshalFunc) FactoryOptions
WithMarshalFunc sets up the specified marshal function. Needs to consider with unmarshal function at the same time.
func WithPubSub ¶
func WithPubSub(pb Pubsub) FactoryOptions
WithPubSub is used to evict keys in local cache
func WithUnmarshalFunc ¶
func WithUnmarshalFunc(f UnmarshalFunc) FactoryOptions
WithUnmarshalFunc sets up the specified unmarshal function. Needs to consider with marshal function at the same time.
type MGetterFunc ¶
MGetterFunc should response a slice of elements which has 1-1 mapping with the provided keys
type MSetOptions ¶
type MSetOptions func(opts *msetOptions)
MSetOptions is an alias for functional argument.
func WithOnCostAddFunc ¶
func WithOnCostAddFunc(f func(key string, cost int)) MSetOptions
WithOnCostAddFunc sets up the callback when adding the cache with key and cost.
func WithOnCostEvictFunc ¶
func WithOnCostEvictFunc(f func(key string, cost int)) MSetOptions
WithOnCostEvictFunc sets up the callback when evicting the cache with key and cost.
type MarshalFunc ¶
MarshalFunc specifies the algorithm during marshaling the value to bytes. The default is json.Marshal.
type Message ¶
type Message interface { // Topic returns the topic Topic() string // Content returns the content of the message Content() []byte }
Message is the interface to receive messages from message queue
type OneTimeGetterFunc ¶
type OneTimeGetterFunc func() (interface{}, error)
OneTimeGetterFunc should be provided as a parameter in GetByFunc()
type Pubsub ¶
type Pubsub interface { // Pub publishes the message to the message queue with specified topic Pub(context context.Context, topic string, message []byte) error // Sub subscribes messages from the message queue with specified topics Sub(context context.Context, topic ...string) <-chan Message // Close closes the subscription only if Sub() is used. // In other word, should handle un-normal usage when Sub() didn't happen before. Close() }
Pubsub is the interface to deal with the message queue
type Result ¶
type Result interface { Len() int Get(ctx context.Context, index int, container interface{}) error }
Result is the return values from MGet(). You need a for loop to parse whole values.
type Setting ¶
type Setting struct { // Prefix is unique id for a group of the cache. Prefix string // CacheAttributes includes all detail attributes. CacheAttributes map[Type]Attribute // MGetter should be provided when using Cache-Aside pattern MGetter MGetterFunc // MarshalFunc specified the marshal function // Needs to consider with unmarshal function at the same time. MarshalFunc MarshalFunc // UnmarshalFunc specified the unmarshal function // Needs to consider with marshal function at the same time. UnmarshalFunc UnmarshalFunc }
Setting provides a relation between Prefix and detailed Attributes. One Setting stands for a one group of a cache, and it use Prefix stands for the unique id. In other words, a group of a cache has it's own Attributes like TTL.
type TinyLFUOptions ¶
type TinyLFUOptions func(opts *tinyLFUOptions)
TinyLFUOptions is an alias for functional argument.
func WithOffset ¶
func WithOffset(offset time.Duration) TinyLFUOptions
WithOffset sets up the offset which is used to randomize TTL preventing expiring at the same time.
type Type ¶
type Type int32
Type decides which components are used in multi-layer cache structure
const ( // NoneType NoneType Type = iota // The famous frameworks are Redis, Memcached, ... (Ref: https://en.wikipedia.org/wiki/Distributed_cache) SharedCacheType // LocalCacheType means private caching in a single application instance, and the most basic type of cache is an in-memory store. // It's held in the address space of a single process and accessed directly by the code that runs in that process. // Due to the limited space of memory, we need to consider the efficient cache eviction policy to keep the most important // items in it. (Ref: https://en.wikipedia.org/wiki/Cache_replacement_policies) LocalCacheType )
All kinds of cache component type
type UnmarshalFunc ¶
UnmarshalFunc specifies the algorithm during unmarshaling the bytes to the value. The default is json.Unmarshal