Pull to refresh

Comments 24

Использую систему лока ключей кеша. Первый процесс делает лок, остальные ждут.
данный пост предлагает не ждать, а вы своим комментом опять предлагаете ждать… зачем???

нужно просто начинать делать SQL запрос раньше времени устаревания на время выполнения запроса(среднее время выполнения запроса + запас)… т.к. в разное время суток(или по др. признаку) среднее время может меняться, то его хорошо бы всегда считать и хранить вместе с результатами запроса…

таким образом 1 процесс зависнет на 1 секунду выполняя запрос, а остальные в это время ещё получают актуальные(т.к. время жизни ещё не истекло) данные из memcached…
Устаревание по времени это только один из use-case'ов. При этом достаточно равномерно распределенынй по времени. В остальных двух (когда данных вообще нет в кеше и, что более ресурсоемко и концентрированно во времени, сброс тегов) что делать? Предуагадать когда момент устаревания тега невозмоно. Поэтому чтобы не городить огород, думаю лучше всегда ждать.
1. если данных нет, понятное дело придётся ждать…

2. данные есть, всегда берём из memcached и только один готовит новую порцию данных заранее… остальные никогда не ждут.

3. если ключ зависит от тега, а тег изменился — значит по новому ключу данных нет, а это 1й случай… (даже прогать ничё не надо)

PS: Коль уж зачем городить огород, зачем вообще браться за memcached, брать из базы да и всё… Да и вообще зачем прогать…
99% вероятность что любой SQL-запрос по выборке товаров в магазине не будет выполняться 10 секунд. Там просто нечего так долго искать.

Надо не кеш собственный делать а проверить структуру таблиц и запросов. Тем более что любой взрослый SQL-сервер сам кеширует данные результатов запросов и делает это очень эффективно.
Меня всегда умиляет, когда о проектировании системы кэширования пишут в трех пунктах и за основу берут какой-нибудь интернет-магазинчик, у которого просто чуть-чуть выросла посещаемость.

Лушче напишите в девяносто седьмой раз о локах, гонках, о кольцевом кэшировании, о тэгах и версионных тэгах в кэше.
Порекомендуйте хорошую статью, что ли.
Чистить кэш по времени и заполнять его новым значением по крону своим скриптом.

1. Сгенерили кэш
2. Записали в базу
3. Стерли старый (если не перезаписан в пункте 1)
В пункте 2, конечно.

P.S.: в пункте 2 базу заменить на любое другое хранилище кэша на вашем сервере.

Блокировка реализуется гораздо проще.
Как уже было сказано выше, небольшой инет-магазин просто не может генерировать такие нагрузки. Скорее всего, проблема в структуре БД или неоптимальных запросах. Выкладывайте свои запросы (желательно с планами), будем разбираться. Можно в личку.
bitrix иногда делает такие штуки
тогда нужно писать битриксу что у них руки кривые :) ибо 10 секунд на запрос, это просто извините. тут нет слов.
Алгоритм должен быть такой: строим новый кэш -> удаляем старый + блокировка.
Тот же MySQL умеет кэшировать запросы. Едиственное но, он использует ключ для кэша — сам sql запрос, мало того, ключ регистрозависим.
аккуратнее уважаемый. а то по вашим стопам не дай бог новичок пойдет и бездумно сделает именно в том порядке что вы указали :))

блокировка, строим новый кеш, удаляем старый, снимаем блокировку.

Извиняюсь, я имел в виду использование блокировки вообще.
я это понял, многие это поняли, вы это понимаете. а многие не понимают. статьи ведь такие пишут ;)
Странно, что никто еще не написал про memcached :)
проглядел, сорри :)
судя по всему вам надо грубо говоря 1 запрос — почему бы не делать это по крону и класть в кеш?
Судя по тому, что у кеша есть время жизни (думаю, не меньше часа, учитывая, что приходится 10 сек запрос выполнять — иначе смысле нет), на сайте интернет-магазина не очень большой товарооборот, иначе топ10 просто не будет отображать реальную ситуацию. В этом случае, целесообразно создать новую таблицу типа
CREATE
    TABLE MART.GOODSCNT
    (
    	--Идентификатор товара
        GID INTEGER NOT NULL,
        --Количество товара
        GCNT INTEGER,
        CONSTRAINT GD_PK PRIMARY KEY (GID)
    )

Эта таблица будет содержать столько строк, сколько различных единиц товара есть в вашем магазине (могу предположить, что различных позиций меньше 100К).
Затем, на таблицу покупок можно повесить триггер, который бы обновлял(или добавлял) значение в таблицу MART.GOODSCNT. Учитывая мое предположение, что товарооборот не слишком велик, дополнительная нагрузка на базу будет незначительной.
В этом случае будет довольно просто вывести топ10 (вместо SELECT COUNT(), который вы, возможно используете)
SELECT GID FROM MART.GOODSCNT ORDER BY GCNT DESC FETCH FIRST 10 ROWS ONLY


Второй вариант, который мне приходит в голову — это создание материализованных таблиц, которые специально созданы для кеширования результатов запроса в виде таблицы. Не факт, правда, что используемая вами СУБД их поддерживает. Если такие таблицы поддерживаются, вам потребуется лишь настроить расписание их обновления.

Третий вариант — создание специализированного хранилища данных (Data warehouse) и ETL-jobs для переливки и агрегации аналитических данных. Но, в случае с небольшим интернет магазином это решение слишком дорогостоящее.

Все эти варианты можно рассматривать, если вы уверены, что текущими средствами не удается добиться прироста производительности вашего SQL запроса.
В целом, я согласен с комментарием . 10 секунд слишком много для выполнения запросов по интернет магазину. Для примера, могу сказать, что на моей практике формирование аналитического запроса с таблицей фактов >37M строк занимает 5-6 секунд.
Sign up to leave a comment.

Articles