Concurrency-safe Go caching library with expiration capabilities and access counters

Overview

cache2go

Latest Release Build Status Coverage Status Go ReportCard GoDoc

Concurrency-safe golang caching library with expiration capabilities.

Installation

Make sure you have a working Go environment (Go 1.2 or higher is required). See the install instructions.

To install cache2go, simply run:

go get github.com/muesli/cache2go

To compile it from source:

cd $GOPATH/src/github.com/muesli/cache2go
go get -u -v
go build && go test -v

Example

package main

import (
	"github.com/muesli/cache2go"
	"fmt"
	"time"
)

// Keys & values in cache2go can be of arbitrary types, e.g. a struct.
type myStruct struct {
	text     string
	moreData []byte
}

func main() {
	// Accessing a new cache table for the first time will create it.
	cache := cache2go.Cache("myCache")

	// We will put a new item in the cache. It will expire after
	// not being accessed via Value(key) for more than 5 seconds.
	val := myStruct{"This is a test!", []byte{}}
	cache.Add("someKey", 5*time.Second, &val)

	// Let's retrieve the item from the cache.
	res, err := cache.Value("someKey")
	if err == nil {
		fmt.Println("Found value in cache:", res.Data().(*myStruct).text)
	} else {
		fmt.Println("Error retrieving value from cache:", err)
	}

	// Wait for the item to expire in cache.
	time.Sleep(6 * time.Second)
	res, err = cache.Value("someKey")
	if err != nil {
		fmt.Println("Item is not cached (anymore).")
	}

	// Add another item that never expires.
	cache.Add("someKey", 0, &val)

	// cache2go supports a few handy callbacks and loading mechanisms.
	cache.SetAboutToDeleteItemCallback(func(e *cache2go.CacheItem) {
		fmt.Println("Deleting:", e.Key(), e.Data().(*myStruct).text, e.CreatedOn())
	})

	// Remove the item from the cache.
	cache.Delete("someKey")

	// And wipe the entire cache table.
	cache.Flush()
}

To run this example, go to examples/mycachedapp/ and run:

go run mycachedapp.go

You can find a few more examples here. Also see our test-cases in cache_test.go for further working examples.

Issues
  • Question about SetAddedItemCallback

    Question about SetAddedItemCallback

    hello 请看如下函数,是不是应该将这这段注释掉 func (table *CacheTable) SetAddedItemCallback(f func(*CacheItem)) {

    //if len(table.addedItem) > 0 {
    //	table.RemoveAddedItemCallbacks()
    //}
    table.Lock()
    defer table.Unlock()
    table.addedItem = append(table.addedItem, f)
    

    }

    opened by NicholasLiuWei 3
  • fix missing dots

    fix missing dots

    Package Testing of go 1.11 is more strict about arguments checking to print-like functions. We will get the error bellow if we left args without dots.

    go test -v
    # github.com/muesli/cache2go
    ./cachetable.go:330: missing ... in args forwarded to print-like function
    FAIL    github.com/muesli/cache2go [build failed]
    

    OS version: manjaro 18.0.0-rc go 1.11.1

    opened by Jnchk 3
  • [BUG] Fatal ERROR when concurrent map write and read

    [BUG] Fatal ERROR when concurrent map write and read

    go version

    go version go1.9 darwin/amd64
    

    log

    fatal error: concurrent map iteration and map write
    
    goroutine 177777 [running]:
    runtime.throw(0xbeb3a9, 0x26)
    	/go1.9/src/runtime/panic.go:605 +0x95 fp=0xc422b05610 sp=0xc422b055f0 pc=0x42e9f5
    runtime.mapiternext(0xc422b05768)
    	/go1.9/src/runtime/hashmap.go:778 +0x6f1 fp=0xc422b056a8 sp=0xc422b05610 pc=0x40d0a1
    github.com/muesli/cache2go.(*CacheTable).expirationCheck(0xc42007e060)
    	/src/github.com/muesli/cache2go/cachetable.go:111 +0x247 fp=0xc422b057d8 sp=0xc422b056a8 pc=0x578d97
    runtime.goexit()
    	/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc422b057e0 sp=0xc422b057d8 pc=0x45f7b1
    created by github.com/muesli/cache2go.(*CacheTable).expirationCheck.func1
    	/src/github.com/muesli/cache2go/cachetable.go:137 +0x3e
    
    duplicate 
    opened by daymade 3
  • go1.8 can't iterate over map while writing to it

    go1.8 can't iterate over map while writing to it

    I upgrade golang to 1.8 and encounter this panic while using cache2go:

    goroutine 363453 [running]: runtime.throw(0x94121a, 0x26) /usr/local/go/src/runtime/panic.go:596 +0x95 fp=0xc420513de0 sp=0xc420513dc0 runtime.mapiternext(0xc420513f68) /usr/local/go/src/runtime/hashmap.go:737 +0x7ee fp=0xc420513e90 sp=0xc420513de0 github.com/muesli/cache2go.(*CacheTable).expirationCheck(0xc4201d2540) /Users/geomantic/Documents/develop/gopath/src/github.com/muesli/cache2go/cachetable.go:111 +0x336 fp=0xc4205 13fd8 sp=0xc420513e90 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2197 +0x1 fp=0xc420513fe0 sp=0xc420513fd8 created by github.com/muesli/cache2go.(*CacheTable).expirationCheck.func1 /Users/geomantic/Documents/develop/gopath/src/github.com/muesli/cache2go/cachetable.go:137 +0x3e

    bug 
    opened by ZGeomantic 3
  • why not move table.Lock() into table.addInternal()?

    why not move table.Lock() into table.addInternal()?

    func (table *CacheTable) Add(key interface{}, lifeSpan time.Duration, data interface{}) *CacheItem {
    	item := NewCacheItem(key, lifeSpan, data)
    
    	// Add item to cache.
    	table.Lock()
    	table.addInternal(item)
    
    	return item
    }
    

    In general,Lock() and UnLock() is pair in function,why not move table.Lock() into table.addInternal()?Is there anything other to consider?

    opened by yiyang5055 2
  • Panic occurs when you use the new create struct to access the key

    Panic occurs when you use the new create struct to access the key

    Hello, I am a Golang novice. When I was learning your code, I found that I used new() to create the struct. When I access the data, panic prompt Err :nil.Is this a bug?

    question 
    opened by sandaawa 1
  • Why creating a Cache requires Double check whether the table exists or not.

    Why creating a Cache requires Double check whether the table exists or not.

    // Cache returns the existing cache table with given name or creates a new one
    // if the table does not exist yet.
    func Cache(table string) *CacheTable {
    	mutex.RLock()
    	t, ok := cache[table]
    	mutex.RUnlock()
    
    	if !ok {
    		mutex.Lock()
    		t, ok = cache[table]
    		// Double check whether the table exists or not.
    		if !ok {
    			t = &CacheTable{
    				name:  table,
    				items: make(map[interface{}]*CacheItem),
    			}
    			cache[table] = t
    		}
    		mutex.Unlock()
    	}
    
    	return t
    }
    
    opened by CoolLiuzw 1
  • table.addedItem does not need to be a array

    table.addedItem does not need to be a array

    if table.addedItem is set, we will remove it before we reset it. so table.addedItem will be always just one item, it didn't need to be a array. table.aboutToDeleteItem is the same.

    `func (table *CacheTable) SetAddedItemCallback(f func(*CacheItem)) {

    // 如果已存在回调函数,则置空
    if len(table.addedItem) > 0 {
    	table.RemoveAddedItemCallbacks()
    }
    table.Lock()
    defer table.Unlock()
    table.addedItem = append(table.addedItem, f)
    

    }`

    opened by ahdong2007 1
  • How about start a channel to exec callback

    How about start a channel to exec callback

    Thanks for your open source.

    if the CacheTabls's items becomes very long and the 'expirationCheck' is runing with lots of callback function waiting to execute, it will lock the table for so many time. so I think it' better to make a channle to exec the callback function.

    opened by aireet 1
  • question about go use

    question about go use

    In file cache.go

    if !ok { t = &CacheTable{ name: table, items: make(map[interface{}]*CacheItem), }

      mutex.Lock()
      cache[table] = t
      mutex.Unlock()
    

    }

    return t

    the assigment function of cache item is

      t = &CacheTable{ ... }
    

    The "t = &CacheTable" seems to be stored at stack , and can not be reentrant after function returns. How could I understand this ? Thanks.

    opened by sunxiao2010n 1
  • Maybe is problem with Less function although this function is unused.

    Maybe is problem with Less function although this function is unused.

    func (p CacheItemPairList) Less(i, j int) bool { return p[i].AccessCount > p[j].AccessCount } #I think it should be: return p[i].AccessCount < p[j].AccessCount

    #Is that right?

    opened by spring410 1
  • Feature: get the value but not update the expiration time (#57)

    Feature: get the value but not update the expiration time (#57)

    Hi @muesli , As suggested in the Issue https://github.com/muesli/cache2go/issues/57 by you, here is my PR incl. test cases for review.I'm so sorry I only recently noticed your reply on #57 .

    opened by sirodeneko 0
  • Feature for the possibility of deletion based on create time.

    Feature for the possibility of deletion based on create time.

    Hi @muesli, As suggested in the Issue #57 by you, here is my PR incl. test cases for review.

    After taking a closer look at the code and now understanding very well how the internal cleanup process works I came to the following solution. By the way, I have to mention that my approach is very similar to #45. I saw it by chance after I had finished my solution. =) It shows that some had the same idea and probably the need for it.

    I am very curious about your feedback

    opened by dreamblack86 1
  • CacheTable.Add() should  not use  “defer table.unlock ”

    CacheTable.Add() should not use “defer table.unlock ”

    CacheTable.Add() function ,must not use "defer table.Unlock()" because addInternal() func will unlock table, that will make duplicate deletion exception

    opened by brightyuan 0
Releases(v0.2)
Owner
Christian Muehlhaeuser
Geek, Gopher, Software Developer, Maker, Opensource Advocate, Tech Enthusiast, Photographer, Board and Card Gamer
Christian Muehlhaeuser
groupcache is a caching and cache-filling library, intended as a replacement for memcached in many cases.

groupcache Summary groupcache is a distributed caching and cache-filling library, intended as a replacement for a pool of memcached nodes in many case

Go 11.6k Aug 8, 2022
Design and Implement an in-memory caching library for general use

Cache Implementation in GoLang Problem Statement Design and Implement an in-memory caching library for general use. Must Have Support for multiple Sta

null 1 Dec 28, 2021
MySQL to Redis caching made easy

redisql MySQL to Redis caching made easy

Tarek Ali 60 May 24, 2022
Redis caching layer for Cloudflare KV in Golang

Redis caching layer for Cloudflare KV in Golang

Dinesh Sonachalam 30 May 21, 2022
Multi-level caching service in Go

IgoVIUM Multi-level caching service in Go. Specifically: Distributed in-memory cache (L1) DB-based cache (L2) Long term historization on persistent vo

Andrea 7 Dec 23, 2021
POC de caching en Go en utilisant go-redis/cache

Test-web POC de caching en Go en utilisant go-redis/cache, cette lib permet d'avoir un cache local et un cache redis (appel cache local puis cache red

HUANG Manutea 0 Nov 19, 2021
API Cache is a simple caching server, using grpc to accept messages.

API Cache is a simple caching server, using grpc to accept messages. It allows to store key-value pairs, where key is string and value is []byte.

null 1 Nov 16, 2021
A simple generic in-memory caching layer

sc sc is a simple in-memory caching layer for golang. Usage Wrap your function with sc - it will automatically cache the values for specified amount o

motoki317 8 Jul 2, 2022
🧩 Redify is the optimized key-value proxy for quick access and cache of any other database throught Redis and/or HTTP protocol.

Redify (Any database as redis) License Apache 2.0 Redify is the optimized key-value proxy for quick access and cache of any other database throught Re

Dmitry Ponomarev 2 Mar 21, 2022
fastcache - fast thread-safe inmemory cache for big number of entries in Go

Fast thread-safe inmemory cache for big number of entries in Go. Minimizes GC overhead

VictoriaMetrics 1.5k Aug 3, 2022
Light weight thread safe cache for golang

go-cache Light weight thread safe LRU cache Getting started import( "fmt" "github.com/tak1827/go-cache/lru" ) func main() { size := 2 cache := l

tak 1 Dec 12, 2021
This provides the lru package which implements a fixed-size thread safe LRU cache

golang-lru This provides the lru package which implements a fixed-size thread sa

byx 0 Dec 22, 2021
Rotating cache for small data with lock-free access.

Rotating cache Byte cache implementation with lock-free access. Designed to work with small data under high pressure. Lock-free access (both read and

Voykov Konstantin 0 Dec 5, 2021
A Lightweight "Remote Cache Access" (Rekas) Framework

Rekas 项目介绍 Rekas:一个轻量级分布式缓存系统 框架 ,解决缓存系统中出现的缓存击穿[锁机制]、缓存穿透[布隆过滤器]、缓存雪崩[分布式]问题,实现

null 6 Jun 21, 2022
Cache library for golang. It supports expirable Cache, LFU, LRU and ARC.

GCache Cache library for golang. It supports expirable Cache, LFU, LRU and ARC. Features Supports expirable Cache, LFU, LRU and ARC. Goroutine safe. S

Jun Kimura 2k Aug 14, 2022
Ristretto - A fast, concurrent cache library built with a focus on performance and correctness

Ristretto Ristretto is a fast, concurrent cache library built with a focus on pe

Koichi Shiraishi 1 Mar 23, 2022
☔️ A complete Go cache library that brings you multiple ways of managing your caches

Gocache Guess what is Gocache? a Go cache library. This is an extendable cache library that brings you a lot of features for caching data. Overview He

Vincent Composieux 1.4k Aug 4, 2022
An in-memory cache library for golang. It supports multiple eviction policies: LRU, LFU, ARC

GCache Cache library for golang. It supports expirable Cache, LFU, LRU and ARC. Features Supports expirable Cache, LFU, LRU and ARC. Goroutine safe. S

Jun Kimura 318 May 31, 2021