попросили его на мапе сделать кеш ин мемори, ну он сделал, с rw мьютексом, потом говорят ну вот у нас нагрузка на него 100500 мильенов и на мьютексах тратится время как обойти проблему? Решили шардировать мапу (в структуре что представляет из себя кеш слайс мап), в итоге он завалил эту задачу. Но я так прикинул, блин а как бы я её делал и походу тоже завалил бы. Ну допустим в методе Get мы по ключу находим кеш, потом по индексу равному кеш%длина слайса кладём мапу, ток слайс же тоже не потокоьезопасен все равно мьютекс нужен, то ж на то и выходит
Атомиками нужно было?
Там вроде надо думать в сторону щардирование с map[string]map[string]string
А какая разница мьютексах все равно нужно использовать
Кажется что от них не уйти, тип можно подумать в сторону sync.Map , но по моему она в данном случае не на много поможет
мьютекс на каждый шард и на саму коллекцию шардов надо
И за счёт чего будет выигрыш?
за счет того, что когда ты мутируешь какой-то ключ и берешь WLock, ты берешь эксклюзивную блокировку только на один шард, а из других шардов в это время можно читать, получая неэксклюзивную блокировку RLock
Хотя не, всеравно в Get/Set нужно делать лок (на весь гет/ сет) т.к. Нужно сделать потоеобезопасно чтение и запись в слайс шардов (в элемент слайса)
Классика, создаёшь массив мап и массив мьютексов. Индекс в массиве это хеш от ключа. Вычисляешь хеш ключа и рв-лок на нужную мапу на запись. Главное хорошую хеш-функцию подобрать.
В гет/сет ты будешь делать RLock почти всегда, WLock исключительно редко, а RLock неэксклюзивный и в целом должен работать быстрее. Ну или можно сделать массив бакетов иммутабельным, как Иван выше подсказал, что позволит избавиться от одного лока и в целом упростит задачу.
не надо на коллекцию шардов, ты их заранее определяешь, они статические
https://github.com/patrickmn/go-cache/tree/master
такое на литкоде обьясняют?
нет конечно, литкод проверяет алгоритмическое мышление, вопрос на дизайн потокобезопасного мемкеша про примитивы синхронизациии имхо
это была неудавшаяся провокация, на поиск источника мудрости) запрос на источник знаний
я работал шарпистом, а "библия" шарпа, которая clr via c#, неплохо объясняет примитивы. и по работе задачи такого рода попадались.
При таких мильонах операций может возникать cache contention и вот там уже sync.Map хорошо себя проявит На хабре как-то видел статью об этом Это вряд ли даст такой же ощутимый выигрыш как шардирование, но иметь ввиду стоит
а чем он не потокобезопасен, если мы его не меняем? и да, обычно размер бакетов фиксированные и можно обойтись массивами
Можно иметь две мапы: обычную и мапу мьютексов. Ключи в двух мапах одинаковые. Тогда при обновлении обычной мапы будем лочить не целую мапу, а лишь key-value поле
Что-то не совсем понял зачем лочить мапу, можно сделать два метода readMap с локом на чтение и setMap с локом на запись и через них осуществлять доступ к мапе
Можно, но в условии сказано, что это будет медленно
все равно будет крашить на записях
При добавлении новых записей в мапу - да. При обновлении существующих - нет
не бывает обновления существующих разве что в мапе вы храните указатель, и тогда обновление мапы касается только в части чтения
Обсуждают сегодня