В качестве высокопроизводительной системы хранения на основе памяти с открытым исходным кодом (BSD) Redis широко используется крупными интернет-компаниями и имеет множество сценариев применения. Эта статья подробно объяснит основное применение и практику Redis в веб-проектах на основе PHP.
тайник
Представленный здесь кеш относится к данным, которые могут быть потеряны или просрочены. Общие командыset
, hset
, get
, hget
, вам необходимо обратить внимание на следующие проблемы при использовании Redis в качестве кеша:
- Из-за ограниченной памяти redis невозможно добиться бесконечного роста памяти Redis.
maxmemory
максимальная память. - Когда maxmemory включен, можно включить механизм lru для установки срока действия ключа.Когда будет достигнут максимальный объем памяти Redis, Redis автоматически удалит ключ в соответствии с наименее использовавшимся алгоритмом.
- Стратегия персистентности Redis и время восстановления после сбоя Redis — это игровой процесс.Если вы хотите восстановиться как можно быстрее в случае сбоя, вам следует включить механизм резервного копирования дампа, но для этого требуется больше доступного места в памяти для персистентности. . Если вы можете мириться с длительным временем восстановления после сбоя Redis, вы можете использовать механизм сохраняемости AOF и отключить механизм дампа, который не требует дополнительного места в памяти.
место хранения
В веб-проектах Redis может хранить данные, которые считываются и записываются очень часто, чтобы уменьшить нагрузку на такие базы данных, как MySQL. Если в качестве системы хранения используется Redis, во избежание потери данных необходимо включить сохраняемость.
Типичная сцена
- прилавок
Потребность в счетчиках очень распространена, например, количество лайков Weibo, количество избранных постов, количество перепостов статей и количество подписчиков пользователей.
- социальный список
Например, используйте структуру Sets для хранения списков наблюдения, списков избранного, списков лайков и т. д.
- Session
Благодаря высокопроизводительному хранилищу ключей и значений redis статус входа пользователя можно сохранить в redis.
- ...
очередь
простая очередь
Обычно списковая структура Redis используется как очередь.rpush
Новости производства,lpop
потреблять сообщения, когдаlpop
При отсутствии сообщения следует выполнить соответствующую операцию ожидания.
$queueKey = "queue";
// 生产者
$redis->rpush($queueKey, $data)
// 消费者
while (true) {
$data = $redis->lpop($queueKey);
if (null === $data) {
usleep(100000);
continue;
}
// 业务逻辑
...
}
Поскольку событие сна, используемое при отсутствии сообщения, нелегко контролировать, старайтесь не использовать сон для сна в производственной среде, вы можете использоватьblpop
для потребления сообщений, а когда новых сообщений нет, он будет блокироваться до тех пор, пока сообщение не поступит.
очередь задержки
Очередь задержки может использовать Redissorted set
структура данных, используя метку времени какscore
, содержание сообщенияmember
,использоватьzadd
команда для создания сообщений, потребители используютzrangebyscore
Команда получает опрос данных сообщения до указанного времени обработки.
$queueKey = "queue";
// 生产消息
// 消费时间, 这里设置为1小时候
$consumeTimestamp = time() + 3600;
// $data需要添加随机串前缀(or后缀),防止出现重复member被丢弃
$data = $data . md5(uniqid(rand(), true));
$redis->zadd($queueKey, $consumeTimestamp, $data);
// 消费消息
while (tue) {
$arrData = $redis->zrangebyscore($queueKey, 0, time());
if (!$arrData) {
usleep(100000);
continue;
}
// 业务逻辑
foreach ($arrData as $data) {
$data = substr($data, 0, strlen($data) - 32);
// 消费$data
}
}
многопользовательский
Используя шаблон подписчика темы публикации/подписки, можно реализовать очередь сообщений 1:N. В этом режиме, когда потребитель выходит из сети, созданное сообщение будет потеряно, что здесь не рекомендуется.
Следует подчеркнуть, что не рекомендуется использовать Redis в качестве службы очереди сообщений, что не является целью разработки Redis. Если вы должны использовать его, подумайтеdisque, разработан автором redis.
Распределенная блокировка
Распределенные блокировки в основном решают несколько задач:
- Взаимное исключение: только один сервис (или приложение) может получить доступ к ресурсу одновременно
- Безопасность: блокировки могут быть сняты только службой (или приложением), удерживающей блокировку.
- Отказоустойчивость: блокировки по-прежнему могут быть сняты при сбое службы, удерживающей блокировку.
- избежать тупика
план 1
мы можем рассмотреть возможность использованияsetnx
а такжеexpire
Команда для достижения блокировки, то есть при отсутствии ключа значение будет успешно записано:
$lockStatus = $redis->setnx($lockKey, 1);
if (1 === $lockStatus) {
// 加锁成功,为锁设置超时时间
$redis->expire($lockKey, 300);
// 进行后续操作
} elseif (0 === $lockStatus) {
// 加锁失败
} else {
// 其他异常
}
Однако эта операция не является атомарной, если во время setnx произойдет сбой сервиса, а времени на установку таймаута на Ключе нет, блокировка никогда не будет снята.
Сценарий 2
мы рекомендуемset key value [EX seconds] [PX milliseconds] [NX|XX]
команда на блокировку
- EX: через сколько секунд истекает срок действия ключа
- PX: через сколько миллисекунд истекает срок действия ключа
- NX: когда ключ не существует, ключ создается, эффект эквивалентен setnx
- XX: если ключ существует, перезаписать ключ
$lockStatus = $this->redis->set($lockKey, 1, "EX", 30, "NX");
if ("OK" === $lockStatus) {
// 加锁成功,可进行后续操作
//业务逻辑执行完毕,释放锁
$this->redis->del($lockKey);
} elseif (null === $lockStatus) {
// 加锁失败
}
Как показано в приведенном выше коде, еслиset
Команда возвращает OK, после чего клиент может получить блокировку (если она возвращает значение null, служба приложения может повторить попытку получения блокировки через некоторое время) и можетdel
Команда для отпускания блокировки.
Этот метод требует внимания к проблеме:
- Блокировка (ключ), полученная службой a, была удалена сервером redis, поскольку срок действия истек, но в это время служба все еще выполняет команду DEL. И служба b повторно получает блокировку с тем же ключом после истечения срока действия, установленного параметром a, затем выполняется a.
del
Блокировка, добавленная службой b, будет снята. - Когда срок действия большого количества ключей истекает одновременно, удаление ключей приведет к увеличению давления повторного доступа и повлияет на стабильность службы.
Приведенную выше систему блокировки можно сделать более надежной за счет следующих оптимизаций:
- Вместо того, чтобы задавать фиксированную строку, задайте для нее случайную большую строку, которую можно назвать токеном.
- Удалить ключ указанного замка скриптом, вместо
del
Заказ. - Добавить случайное значение при установке срока действия ключа.
Оптимизированный код может относиться к следующему:
$lockToken = md5(uniqid(rand(), true));
// 此处超时时间根据具体业务逻辑配置
$expire = rand(280, 320);
$lockStatus = $this->redis->set($lockKey, $lockToken, "EX", $expire, "NX");
if ("OK" === $lockStatus) {
// 加锁成功,可进行后续操作
// 业务逻辑执行完毕,释放锁
// 删除锁之前需要判断是否是自己上的锁
$currentToken = $this->redis->get($lockKey);
if ($currentToken === $lockToken) {
$this->redis->del($lockKey);
}
} elseif (null === $lockStatus) {
// 加锁失败
}
рассчитать
Метод атомарного самоувеличения и упорядоченная структура набора, предоставляемые Redis, могут выполнять некоторые вычислительные задачи, такие как статистика просмотров страниц.
Количество просмотров
Просмотры статьи +1
$redis->incr($postsKey);
Получите просмотры статей в пакетном режиме
$arrPostsKey = [
//...
];
$arrPostsViewNum = $redis->mget($arrPostsKey);
Таблица лидеров
Вы можете использовать упорядоченный набор redis для реализации функции таблицы лидеров, а баллы используются в качестве веса для сортировки и взятия первых n записей.
// 存储数据
$sortKey = "sort_key";
$redis->zadd($sortKey, 100, "tom");
$redis->zadd($sortKey, 80, "Jon");
$redis->zadd($sortKey, 59, "Lilei");
$redis->zadd($sortKey, 87, "Hanmeimei");
// 获取排行
// 由大到小排序
$arrRet = $redis->zrevrange($sortKey, 0, -1, true);
// 由小到大排序
$arrRet = $redis->zrange($sortKey, 0, -1, true);
конец
В Redis задействовано множество практик применения. Из-за ограниченного объема в этой статье представлены только наиболее часто используемые сценарии в веб-приложениях. Студенты, которые хотят еще больше расширить свои знания о Redis, могут обратиться к следующим ссылкам для дальнейшего изучения.
Оригинальная ссылка:Применение и практика Redis в веб-проектах
Отсканируйте код и подпишитесь на общедоступную учетную запись WeChat: Learn2Code