синхронизация mysql и memcached / membase - PullRequest
1 голос
/ 23 января 2012

У меня есть приложение, в котором я хотел бы свернуть определенную информацию в мембрану, чтобы избежать дорогостоящей группировки по запросам.Например, преобразование кликов будет записано в MySQL, и я хочу сохранить общее количество кликов, сгруппированных по часам для определенного пользователя, в ключе memcache.Там я могу разархивировать / сериализовать массив с нужными мне значениями.У меня есть много других потребностей, таких как доход, лайки и т. Д.

Каков наилучший способ создания некой «транзакции», которая гарантирует синхронизацию MC и Mysql?Я всегда мог перестроить хранилище ключей на основе основного хранилища MySQL, но я хотел бы поддерживать хороший параллелизм между этими двумя продуктами.

1 Ответ

0 голосов
/ 10 мая 2012

На высоком уровне, чтобы использовать membase / memcache / etc в качестве кеша для mysql, вам нужно сделать что-то вроде следующего:

public Object readMethod(String key) {
    value = membaseDriver->get(key);
    if(value != null) {
        return value;
    }
    value = getFromMysql(key);
    membaseDriver->put(key, value, TTL);
}

public Object writeMethod(String key, String value) {
    writeToMysql(key, value);
    membaseDriver->delete(key); 
    //next call to get will get the value that we just wrote to db
}

Это гарантирует, что ваша БД остается основным источником данных и гарантирует, что мембрана и mysql остаются почти в синхронизации. (это не в синхронизации, когда процесс выполняет метод записи, после того, как он записал в mysql и до того, как он удалил ключ из мембраны).

Если вы хотите, чтобы они действительно были синхронизированы, вы должны убедиться, что в то время, как какой-либо процесс выполняет writeMethod, ни один процесс не может выполнить readMethod. Вы можете сделать простую глобальную блокировку в memcache / membase, используя метод add. По сути, вы добавляете уникальный ключ, названный в честь вашей блокировки (например, «MY_LOCK»), если добавление завершается успешно, у вас есть блокировка, после этого никто другой не сможет получить блокировку. Когда вы закончите запись, вы снимаете блокировку, вызывая delete с именем ключа вашей блокировки. Запуская оба этих метода с этой «блокировкой» и заканчивая оба этих метода с «разблокировкой», вы гарантируете, что только один процесс одновременно выполняет любой из них. Кроме того, вы могли бы создать отдельные блокировки для чтения и записи, но я не думаю, что блокировка - это действительно то, чего вы хотите, если только вам не нужно быть на 100% обновленным (в отличие от 99,999% на обновлении).

В случае кликов в час можно избежать повторного выполнения запроса при каждом подсчете другого клика, сохранив текущий час (т. Е. Единственный, который изменится) отдельно от массива всех предыдущих часов ( что, вероятно, никогда не изменится, верно?).

Каждый раз, когда вы добавляете клик, просто используйте приращение memcache на счетчике текущего часа. Затем, когда вы получите запрос на чтение, посмотрите массив всех предыдущих часов, затем текущий час и все предыдущие часы с текущим часом, добавленным в конец. В качестве бесплатного бонуса тот факт, что приращение является атомарным, предоставляет вам фактически синхронизированные значения, поэтому вы можете пропустить блокировку.

...