inmem cache sharding improvement

This commit is contained in:
Sergey Chubaryan 2024-08-28 14:50:55 +03:00
parent 2422d2d036
commit 7746add842
2 changed files with 54 additions and 33 deletions

View File

@ -114,21 +114,9 @@ func (a *App) Run(p RunParams) {
userRepo = repos.NewUserRepo(sqlDb) userRepo = repos.NewUserRepo(sqlDb)
emailRepo = repos.NewEmailRepo() emailRepo = repos.NewEmailRepo()
actionTokenRepo = repos.NewActionTokenRepo(sqlDb) actionTokenRepo = repos.NewActionTokenRepo(sqlDb)
jwtCache = repos.NewCacheInmemSharded[string, string](60, 36, func(key string) int { userCache = repos.NewCacheInmemSharded[models.UserDTO](60*60, repos.ShardingTypeInteger)
char := int(key[len(key)-1]) jwtCache = repos.NewCacheInmemSharded[string](60, repos.ShardingTypeJWT)
if char >= 0x30 && char <= 0x39 {
return char - 0x30
}
if char >= 0x41 && char <= 0x5A {
return char - 0x41
}
return char - 0x61
}) //repos.NewCacheInmem[string, string](60)
linksCache = repos.NewCacheInmem[string, string](7 * 24 * 60 * 60) linksCache = repos.NewCacheInmem[string, string](7 * 24 * 60 * 60)
userCache = repos.NewCacheInmemSharded[string, models.UserDTO](60*60, 10, func(key string) int {
char := int(key[len(key)-1])
return char - 0x30
}) //repos.NewCacheInmem[string, models.UserDTO](60 * 60)
) )
// Periodically trigger cache cleanup // Periodically trigger cache cleanup
@ -141,8 +129,8 @@ func (a *App) Run(p RunParams) {
case <-ctx.Done(): case <-ctx.Done():
return return
case <-tmr.C: case <-tmr.C:
jwtCache.CheckExpired()
userCache.CheckExpired() userCache.CheckExpired()
jwtCache.CheckExpired()
linksCache.CheckExpired() linksCache.CheckExpired()
} }
} }

View File

@ -4,52 +4,85 @@ import (
"sync" "sync"
) )
func NewCacheInmemSharded[K comparable, V any]( type ShardingType int
ttlSeconds, shards int,
hashFunc func(key K) int, const (
) Cache[K, V] { ShardingTypeJWT ShardingType = iota
inmems := []*cacheInmem[K, V]{} ShardingTypeInteger
)
type shardingHashFunc func(key string) int
func getShardingInfo(shardingType ShardingType) (int, shardingHashFunc) {
switch shardingType {
case ShardingTypeInteger:
return 10, func(key string) int {
char := int(key[len(key)-1])
return char - 0x30
}
case ShardingTypeJWT:
return 36, func(key string) int {
char := int(key[len(key)-1])
if char >= 0x30 && char <= 0x39 {
return char - 0x30
}
if char >= 0x41 && char <= 0x5A {
return char - 0x41
}
return char - 0x61
}
}
return 1, func(key string) int {
return 0
}
}
func NewCacheInmemSharded[V any](defaultTtlSeconds int, shardingType ShardingType) Cache[string, V] {
shards, hashFunc := getShardingInfo(shardingType)
inmems := []*cacheInmem[string, V]{}
for i := 0; i < shards; i++ { for i := 0; i < shards; i++ {
inmems = append( inmems = append(
inmems, inmems,
&cacheInmem[K, V]{ &cacheInmem[string, V]{
m: &sync.Mutex{}, m: &sync.Mutex{},
data: map[K]*cacheInmemItem[V]{}, data: map[string]*cacheInmemItem[V]{},
ttlSeconds: ttlSeconds, ttlSeconds: defaultTtlSeconds,
}, },
) )
} }
return &cacheInmemSharded[K, V]{ return &cacheInmemSharded[V]{
shards: inmems, shards: inmems,
hashFunc: hashFunc, hashFunc: hashFunc,
} }
} }
type cacheInmemSharded[K comparable, V any] struct { type cacheInmemSharded[V any] struct {
hashFunc func(key K) int hashFunc shardingHashFunc
shards []*cacheInmem[K, V] shards []*cacheInmem[string, V]
} }
func (c *cacheInmemSharded[K, V]) Get(key K) (V, bool) { func (c *cacheInmemSharded[V]) Get(key string) (V, bool) {
return c.getShard(key).Get(key) return c.getShard(key).Get(key)
} }
func (c *cacheInmemSharded[K, V]) Set(key K, value V, ttlSeconds int) { func (c *cacheInmemSharded[V]) Set(key string, value V, ttlSeconds int) {
c.getShard(key).Set(key, value, ttlSeconds) c.getShard(key).Set(key, value, ttlSeconds)
} }
func (c *cacheInmemSharded[K, V]) Del(key K) { func (c *cacheInmemSharded[V]) Del(key string) {
c.getShard(key).Del(key) c.getShard(key).Del(key)
} }
func (c *cacheInmemSharded[K, V]) CheckExpired() { func (c *cacheInmemSharded[V]) CheckExpired() {
for _, shard := range c.shards { for _, shard := range c.shards {
shard.CheckExpired() shard.CheckExpired()
} }
} }
func (c *cacheInmemSharded[K, V]) getShard(key K) *cacheInmem[K, V] { func (c *cacheInmemSharded[V]) getShard(key string) *cacheInmem[string, V] {
index := c.hashFunc(key) index := c.hashFunc(key)
return c.shards[index] return c.shards[index]
} }