01 Фон
Всем привет, я Аму! Ваш урожай — моя симпатия, а ваши симпатии — мое признание.
Когда я только закончил работу много лет назад, можно сказать, что использование кеша в то время было редкостью, и я не могу использовать кеш для разработки курсов или небольших проектов в университете, к тому же мой университет занимается встраиванием. на языке ассемблера и языке c.
В то время стажеры собирались найти работу и не пошли.Интервьюер спросил о разнице между Redis и Memcached? Сумма, я сделал домашнее задание, это была топливозащитная основа Redis и приложение, но оно было не очень знакомым, я ответил на известный выбор. Тогда спросите меня еще раз, если компания теперь является приложением, приложение имеет функцию входа в систему, что вам делать?
«Это сложно?», прямо к интервьюеру и сказал использовать хранилище mysql.
"В настоящее время у нас более 200 000 активных пользователей. Вы уверены, что используете только хранилище mysql? Вы не боитесь взорвать нашу базу данных?" Разве это не было бы так просто?
Совсем недавно маленький друг спросил об этой точке знаний о входе в систему, так что давайте поговорим об этом здесь!
02 Что такое основа растрового изображения?
Официальный сайт говорит:位图не является реальным типом данных, но определен в строковом типебит ориентированныйнабор операций. Наименьшая единица растрового изображениябиты(бит), значение каждого бита может быть только0или1. Максимальный предел строки в Redis составляет512M, поэтому растровое изображение может содержать до 2^32 (4,2 миллиарда) различных битов.
Вы можете думать о растровом изображении как о битовом массиве, а нижний индекс массива — это смещение.
Его преимущества: небольшие накладные расходы на память, высокая эффективность и простота в эксплуатации.
03 Что мы можем делать с растровыми изображениями?
- Подсчет ежедневных регистраций пользователей (наиболее часто используемый)
- Статистика ежедневных/более активных активных пользователей (расширение: точные данные: использование
hiveилиsparkСтатистика; неточные данные, сHyperLogLog) - Онлайн-статистика пользователей в режиме реального времени (около 100 миллионов пользователей: требуется 12 МБ дискового пространства)
- Двойная запись и дедупликация данных
- Статус прочитанного или непрочитанного видео, статей и т. д.
04 Какие команды можно использовать для растрового изображения?
1,найти выбратьКомандная операция:
getbit指令:getbit key offset 获取指定偏移量上的位(bit);时间复杂度O(1)。
注意:
当key不存在或者offset比字符串值的长度大时,则返回0。
bitcount指令:bitcount key [start] [end]获取指定范围内比特位的数量;时间复杂度O(n)。
注意:
当key不存在时会被当成是空字符串来处理,所以返回值为0。
bitpos指令:bittops key bit [start] [end] 获取位图中第一个值为bit的二进制位的位置;时间复杂度: O(n),其中n为位图包含的二进制位数量。
2,добавить вставкуКомандная операция:
setbit指令:setbit key offset value 设置key所储存的字符串值,或清除指定偏移量上的位(bit);时间复杂度:O(1)。
注意:
1、位的设置或清除取决于value参数,0或者1。
2、当key不存在时,自动生成一个新的字符串值。
3、位数组会自动伸展扩充,offet偏移量设置超出现现有的内容范围,为确保value值在指定偏移量上,会通过扩容,空白位置用0填充补上,
4、offet参数值必须大于或者等于0,小于2^32(字符串最大值是512M)
Ниже приведена временная сложность моей сортировки команд хеш-типа, вы можете обратиться к этой таблице:
| инструкция | временная сложность |
|---|---|
| getbit key offset | O(1) |
| bitcount key [start] [end] | O (n), где n - размер числа битов |
| setbit key offset value | O(1) |
| bittops key bit [start] [end] | O(n), где n — количество бит |
05 Практическая серия растровых изображений
Функция, которую мы хотим реализовать, является наиболее часто используемой функцией регистрации. Функции реализации следующие:
- 1. Войдите в систему и введите
- 2. Определите, следует ли отмечаться в определенный день (поскольку в большинстве приложений есть кнопка регистрации только в этот день).
- 3. Получить список записей пользователей за определенный месяц
- 4. Подсчитайте общее количество раз, когда пользователи регистрируются в месяц.
- 5. Получите количество последовательных врезок пользователя в определенный месяц.
- 6. Дополнительная подпись пользователя
Сначала мы создаем реляционную таблицу данных с вводной информацией пользователя для хранения вводной информации пользователя.
Я видел, что многие люди в Интернете используют redis только для хранения информации о пользователях и фактически не имеют с ней дело.Самое странное, что люди спрашивают, что мы должны делать, если redis зависает или что-то в этом роде, операции или продукты хотите получить анализ данных?
Один из блогеров ответил: "Высокая доступность Redis, постоянство Redis, запись интерфейса кеша запросов в фоновом режиме, ты не можешь сделать это? ", следующий комментарий: Блогер ответил серьезно? Пришел нас дразнить? Я тоже посмеялся...
Поговорим о причинах создания табличных записей:
1. В大数据В эту эпоху любая ценная информация должна быть собрана и передана пользователям.活跃度,DAUсвязанное важнее
2. Связан с пользователем,产品и营运Эти данные определенно понадобятся для анализа поведения пользователей и анализа того, что вход в систему и дарение подарков приносят收益
3. Не могуЧрезмерная зависимость от кеша, как только возникает проблема с кешем или сбои, потеря данных становится большой проблемой, и жалобы пользователей значительно увеличиваются.
4.Когда у пользователей есть сомнения, они могут быстро устранить проблему с помощью данных о посадке.
5.При возникновении проблем с кешем данные могут быть возвращены в источник через записи базы данных для обеспечения согласованности данных.
CREATE TABLE `mumu_sign_202105` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增ID',
`user_id` varchar(255) NOT NULL DEFAULT '' COMMENT '用户昵称',
`sign_date` date NOT NULL DEFAULT '0000-00-00' COMMENT '签到时间',
`create_at` int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_uid_date` (`user_id`,`sign_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息基础表';
Мы видим, что эта таблица не очень удивительна, почему принести_202105Ну, в основном используется здесьПринцип деления таблицы по месяцам, Из-за большого количества пользователей постарайтесь обеспечить, чтобы данные таблицы были менее 500 Вт. Конечно, некоторые показатели лучше, чем 1000. После оптимизации скорость также увеличивается.
Однако рекомендуется разделить таблицу по месяцам, после окончания каждого месяца данные можно синхронизировать сулей, эс, сфинксВсе можно, нужно только следить за тем, чтобы данные таблицы в течение полугода, остальное можно было израсходовать и удалить.
Поэтому всякий раз, когда мы проектируем таблицу или делаем функцию, мы должны учитывать предполагаемую сумму и то, почему мы это делаем. Таким образом, вы будете становиться все более и более совершенными, а ваша логика мышления будет становиться все более и более тщательной.
insert into `mumu_user` (`user_id`, `sign_date`,`create_at`) VALUES
('10001','2021-04-22', unix_timestamp()),
('10001','2021-04-24', unix_timestamp()),
('10001','2021-04-25', unix_timestamp()),
('10001','2021-04-26', unix_timestamp()),
('10001','2021-04-30', unix_timestamp());
Тогда приступим к разбору логики кода:
① Серия перфокарт для регистрации
/**
* @desc 签到
* @param string $date
* @return int
*/
public function signIn($date = '')
{
//获取当月用户签到的缓存key
$key = $this->getKey($date);
// this->getCurrentDay 获取当日是本月的第几天并且减去1就是设置位图的下标
return $this->redis->setBit($key, $this->getCurrentDay($date), 1);
}
require_once './Bitmap.php'; //引入位图类
$user_id = 1001; //传入用户ID
$date = "2021-04-24"; //传入指定的签到日期
$bitmap = new Bitmap($user_id); //实例化位图类
echo $bitmap->signIn($date); //输出1
-- 终端操作
localhost:6379> SETBIT user:sign:1001:202104 23 1
(integer) 0
Кажется ли это очень простым, это не что иное, как использование инструкции setbit для сохранения статуса регистрации как 1 для пользователя. Не забудьте вставить таблицу данных перед записью в кеш, чтобы обеспечить успешную посадку базы данных.Smart вы можете увидеть уникальный набор ключей в таблице, цель состоит в том, чтобы гарантировать, что у пользователя будет только одна запись регистрации в день.
② Определить, была ли карта активирована в определенный день
/**
* @desc 判断用户在某一天是否签到
* @param string $date
* @return int
*/
public function judgeUserSign($date = '')
{
$key = $this->getKey($date);
return $this->redis->getBit($key, $this->getCurrentDay($date));
}
require_once './Bitmap.php';
$user_id = 1001;
$date = "2021-04-24";
$bitmap = new Bitmap($user_id);
echo $bitmap->judgeUserSign($date);// 输出值为1
-- 终端操作
localhost:6379> GETBIT user:sign:1001:202104 23 //这里23是指位图下标,因为是从0开始,所以存储时减一操作了 变成了23
(integer) 1
localhost:6379> GETBIT user:sign:1001:202104 24 //这里实际查询的是4月25号是否签到
(integer) 0
③ Получить список записей о врезках пользователей за определенный месяц.
/**
* @desc 获取用户本月签到的记录列表
* @param string $date
* @return mixed
*/
public function getUserAllSign($date = '')
{
// 获取本月或者指定月的签到缓存key
$key = $this->getKey($date);
// 很遗憾 本地reddi并没有支持这个函数
$result = $this->redis->bitField($key); // 正常这里应该返回的是数组 我这里使用不了 相当于模拟
// 存储本月的签到结果集
$list = [];
// 获取指定月的月数
$days = $this->getMonthDays($date);
// 从低位到高位遍历,0表示未签到;1表示已签到
for ($i = $days; $i > 0; $i--) {
// 本月已经循环完直接退出
if ($i < 0) break;
// 定义当前的日期是多少
$local_date = date('Y-m') . '-' . $i;
// 右移再左移,如果不等于自己说明最低位是 1,表示已签到
$flag = ($result >> 1 << 1) != $result ? true : false;
// 如果已签到,添加标记为1,否则为0
$list[$local_date] = $flag ? 1 : 0;
// 然后右移一位重新赋值计算
$result >>= 1;
}
return $list;
}
require_once './Bitmap.php';
$user_id = 1001;
$date = "2021-04-24";
$bitmap = new Bitmap($user_id);
$result = $bitmap->getUserAllSign($date);
var_dump($result);
//执行结果集
array(30) {
["2021-04-30"]=>
int(0)
["2021-04-29"]=>
int(0)
["2021-04-28"]=>
int(0)
["2021-04-27"]=>
int(0)
["2021-04-26"]=>
int(0)
["2021-04-25"]=>
int(0)
["2021-04-24"]=>
int(1)
["2021-04-23"]=>
int(0)
["2021-04-22"]=>
int(0)
["2021-04-21"]=>
int(0)
["2021-04-20"]=>
int(0)
["2021-04-19"]=>
int(0)
["2021-04-18"]=>
int(0)
["2021-04-17"]=>
int(0)
["2021-04-16"]=>
int(0)
["2021-04-15"]=>
int(0)
["2021-04-14"]=>
int(0)
["2021-04-13"]=>
int(0)
["2021-04-12"]=>
int(0)
["2021-04-11"]=>
int(0)
["2021-04-10"]=>
int(0)
["2021-04-9"]=>
int(0)
["2021-04-8"]=>
int(0)
["2021-04-7"]=>
int(0)
["2021-04-6"]=>
int(0)
["2021-04-5"]=>
int(0)
["2021-04-4"]=>
int(0)
["2021-04-3"]=>
int(0)
["2021-04-2"]=>
int(0)
["2021-04-1"]=>
int(0)
}
//我们再看下终端执行的结果
localhost:6379> BITFIELD user:sign:1001:202104 get u30 0
1) (integer) 64
Обратите внимание, что дата 2021-04-24 — это дата, которую мы установили для регистрации выше, а возвращаемые 64 — это двоичные данные: 0100 0000 Это очень ясно, указывая на то, что регистрация 24-го числа
У вас есть сомнения, почему нет поддержки?bitFieldКоманда Redis добавила это мощное битовое поле команды после версии 3.2. r Если такой инструкции нет, считается, что приведенный выше код будет кэшировать данные, полученные пакетами, в течение десятков дней с помощью конвейерных команд. Но с ним это вообще не концепция, он может завершить получение всех значений с помощью одной команды. Популяризируйте команду битового поля:
官方文档:
BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL] 意思是:中括号的意思是指支持它的子命令;get、set、incrby
时间复杂度:O(1)
举个例子解析:
bitfield key get u8 0
1、key指我们需要操作的缓存key
2、get是bitfield的子命令 用来select
3、u8表示无符号数+30位整形位数(i8表示有符号数)
4、0表示返回指定的位偏移量
Популярная наука: так называемое число без знака относится к неотрицательному числу без позиции знака, а полученный массив битов представляет собой все значения; число без знака относится к отрицательному числу, первый бит полученного значения является битом знака , а остальное — доступное значение. Если хотите понять, можете посмотреть принцип компьютерной композиции в биби.
④ Получить общее количество пользователей, пробитых за месяц
/**
* @Desc 获取用户当月打卡总数
* @param string $date
* @return int
*/
public function getSumSignCount($date = '')
{
$key = $this->getKey($date);
return $this->redis->bitCount($key);
}
$bitmap = new Bitmap($user_id);
$result = $bitmap->getSumSignCount($date);
var_dump($result); //结果输出1 因为我们4月份就打卡了一天
//终端执行
localhost:6379> BITCOUNT user:sign:1001:202104
(integer) 1
5 Получите количество пользователей для входа
/**
* @desc 获取用户连续签到的次数
* @param string $date
* @return int
*/
public function getContinuousSignCount($date = '')
{
$key = $this->getKey($date);
// 获取今天天数
$days = $this->getCurrentDay($date);
//// 获取用户从当前日期开始到 1 号的所有签到状态 不过很遗憾 本地reddi并没有支持这个函数
$result = $this->redis->bitField($key, 'u' . $days, 0); // 正常这里应该返回的是数组
// 连续签到计数器总数
$signCount = 0;
$value = isset($result[0]) ? $result[0] : 0;
// 通过位移计算连续签到次数
for ($i = $days; $i > 0; $i--) // i 表示位移操作次数
{
if ($i < 0) break; //超出则终止循环
// 先右移再左移,如果等于自己说明最低位是 0,表示未签到
if ($value >> 1 << 1 == $value) { //存在用户当天还未签到,所以要排除掉
// 低位 0 且非当天说明连续签到中断了
if ($i != $days) break;
} else {
// 如果不等于自己说明最低位是1,表示已经签到
$signCount++;
}
// 右移一位并重新赋值,相当于把最低位丢弃一位然后重新计算
$value >>= 1;
}
return $signCount;
}
$bitmap = new Bitmap($user_id);
$result = $bitmap->getContinuousSignCount($date);
var_dump($result); //执行结果 只有2次连续签到 后面我设置了 20号 24号签到了
//终端执行
localhost:6379> BITFIELD user:sign:1001:202104 get u25 0
1) (integer) 22
Это количество последовательных проверок в основном предназначено для проверки навыков каждого в двоичных битовых операциях, знания того, как выполнять битовые операции, чтобы вы могли лучше узнать, как использовать регистрацию.
Сдвиг влево-вправо под научно-популярной:
b (сдвиг влево) будетb раз (каждый ход означает «умножить на 2»), левая часть справа заполняется нулями, а знаковый разряд удаляется, что означает, что знак не сохраняется.
b (сдвиг вправо) будетb раз (каждый сдвиг означает «делить на 2»); при сдвиге вправо левая часть дополняется знаковым битом, то есть знак сохраняется.
⑥ Дополнительная подпись пользователя
/**
* @desc 用户补签
* @param string $date
* @return bool|int
*/
public function rebuildSign($date = '')
{
$key = $this->getKey($date);
// 先检测当前用户这一天是否已经签到
if ($this->judgeUserSign($date)) return false;
return $this->signIn($date);
}
//这个就很简单了,大家可以自己操作一下
Адрес склада фактического растрового кода:GitHub.com/Я Аму/Аминь…
окончательное резюме
В этой статье в основном объясняется использование растровых изображений Redis в реальных сценариях приложений. Как применять, как практиковать, через выполнение одного случая кода вы сможете больше понять о том, что происходит с растровым изображением.
Растровое изображение — это строка, которая занимает память и может хранить большое количество данных. Позвольте дать вам небольшой совет.Читая статьи или книги, вы должны практиковаться после их прочтения, т.к.Практика — единственный критерий проверки истины.; Если вы все еще используете set hash simember для функции регистрации, вы можете попробовать изменить и сравнить производительность, а также улучшить наш технический уровень и скорость доступа к интерфейсу.
После прочтения статьи появилось ли у вас понимание использования растровых изображений? Если статья Аму покажется вам полезной или недостаточной, оставьте сообщение под комментариями.
Наконец, приглашаю обратить внимание на мой личный публичный аккаунт»Я Аму«Время от времени обновляйте базовые знания и учебные заметки. Прямая публика также не приветствуется в личном письме или электронной почте, чтобы связаться со мной, мы можем учиться вместе и прогрессировать вместе.
Хорошо, я Аму, рабочий, которого уволили к 30 годам.