Sobes.tech
Назад к вопросам
Junior — Middle
93

Возможно ли реализовать отдельные операции записи и чтения с использованием различных шардов?

Компании, где спрашивали
Indrive

Ответ от нейросети

sobes.tech AI

Да, в Go можно реализовать отдельные операции записи и чтения с использованием различных шардов (частей) для повышения производительности и уменьшения блокировок.

Идея заключается в том, чтобы разбить общую структуру данных на несколько шардов — независимых подструктур, каждая со своей блокировкой (например, mutex). Записи и чтения направляются в соответствующий шард по хешу ключа.

Преимущества:

  • Параллельные операции с разными ключами могут выполняться без взаимных блокировок.
  • Уменьшается конкуренция за одну глобальную блокировку.

Пример упрощённой реализации шардированной карты:

import (
    "hash/fnv"
    "sync"
)

type shard struct {
    sync.RWMutex
    m map[string]interface{}
}

type ShardedMap struct {
    shards []shard
}

func NewShardedMap(numShards int) *ShardedMap {
    shards := make([]shard, numShards)
    for i := range shards {
        shards[i].m = make(map[string]interface{})
    }
    return &ShardedMap{shards: shards}
}

func (sm *ShardedMap) getShard(key string) *shard {
    h := fnv.New32a()
    h.Write([]byte(key))
    return &sm.shards[uint(h.Sum32())%uint(len(sm.shards))]
}

func (sm *ShardedMap) Set(key string, value interface{}) {
    s := sm.getShard(key)
    s.Lock()
    defer s.Unlock()
    s.m[key] = value
}

func (sm *ShardedMap) Get(key string) (interface{}, bool) {
    s := sm.getShard(key)
    s.RLock()
    defer s.RUnlock()
    val, ok := s.m[key]
    return val, ok
}

Таким образом, операции записи и чтения распределяются по разным шардовым мьютексам, что повышает масштабируемость.