Go High-Performance Cache with TTL and Disk Persistence
Leo Antony
Posted on August 13, 2024
1.Introduction
Accelerate your Golang projects without the hassle of setting up a database everytime you begin a new project. Tired of configuring databases from scratch? Only to face new problems? Look no further In this blog we will be looking into Golang caching library with Support for TTL, disk Persistence and Hash Data type.
2.Prerequisite
- Basic Knowledge of Golang
- Knowledge of how a typical cache works
3.Features
- Set & Get command
- Update command
- Del command
- Exists command
- Support for TTL
- Support for Disk Save(Snapshots)
- Support Hash Data type (Hset, Hget, HgetAll, HMset)
- Safe Locking
Set & Get command
import (
"fmt"
"github.com/leoantony72/goswift"
)
func main(){
cache := goswift.NewCache()
// Value 0 indicates no expiry
cache.Set("key", "value", 0)
val, err := cache.Get("key")
if err !=nil{
fmt.Println(err)
return
}
fmt.Println("key", val)
}
Update command
// Update value
// @Update(key string, val interface{}) error
err = cache.Update("key","value2")
if err != nil{
fmt.Println(err)
return
}
Del command && Exists command
// Delete command
// @Del(key string)
cache.Del("key")
// Exist command
// @Exists(key string) bool
value = cache.Exists("key")
fmt.Println(value) // returns false
Support for TTL
// Set Value with Expiry
// @Set(key string, val interface{}, exp int)
// Here expiry is set to 1sec
cache.Set("key","value",1000)
// Hset command
// @Hset(key, field string, value interface{}, exp int)
// in this case the "key" expires in 1sec
cache.Hset("key","name","value",1000)
cache.Hset("key","age",18,1000)
Support Hash Data type (Hset, Hget, HgetAll, HMset)
// Hset command
// @Hset(key, field string, value interface{}, exp int)
// in this case the "key" expires in 1sec
cache.Hset("key","name","value",1000)
cache.Hset("key","age",18,1000)
// HMset command
// @HMset(key string, d interface{}, exp int) error
// Set a Hash by passing a Struct/Map
// ---by passing a struct---
type Person struct{
Name string
Age int
Place string
}
person1 := &Person{Name:"bob",Age:18,Place:"NYC"}
err = cache.HMset("key",person1)
if err != nil{
fmt.Println(err)
return
}
// ---by passing a map---
person2 := map[string]interface{Name:"john",Age:18,Place:"NYC"}
err = cache.HMset("key",person2)
if err != nil{
fmt.Println(err)
return
}
// Hget command
// @HGet(key, field string) (interface{}, error)
// get individual fields in Hash
data,err := cache.HGet("key","field")
if err != nil{
fmt.Println(err)
return
}
fmt.Println(data)
// HgetAll command
// @HGetAll(key string) (map[string]interface{}, error)
// gets all the fields with value in a hash key
// retuns a map[string]interface{}
data,err = cache.HGetAll("key")
if err != nil{
fmt.Println(err)
return
}
Snapshots
opt := goswift.CacheOptions{
EnableSnapshots: true,
SnapshotInterval: time.Second*5,
}
c := goswift.NewCache(opt)
This will take a snapshot of the Data Every 5sec and saves it into a Snapshot.data file. By default Snapshots are disabled and if the SnapshotInterval is not provided default value is 5seconds.
NOTE: If the EnableSnapshot is false, Data saved in the file will not imported
Error handling
const (
ErrKeyNotFound = "key does not Exists"
ErrFieldNotFound = "field does not Exists"
ErrNotHashvalue = "not a Hash value/table"
ErrHmsetDataType = "invalid data type, Expected Struct/Map"
)
These are the common Errors that may occur while writing the code. These Varible provide you a clear and easy Error comparison method to determine errors.
data,err := cache.Get("key")
if err != nil {
if err.Error() == goswift.ErrKeyNotFound {
//do something
}
}
Inner workings of the cache expiry
Every 3sec the **sweaper **function gets called to clear out the expired values from the hash table. We maintain a min heap which points to the hash map. The top element will be the key with the smallest TTL. we traverse through the tree until TTL is greater then the current time.
Summary
I wouldn't advice you to use this in production!!, but feel free to use it in your small side project. Do try it out and if you encounter a bug do make a issue on GitHub repo.
Email: leoantony102@gmail.com
Github: https://github.com/leoantony72
Repo: https://github.com/leoantony72/goswift
Posted on August 13, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.