Помимо sql баз данных, вроде использованного ранее MySQL, Postgres, Oracle и т.д. есть целый класс хранилищ данных, которые не поддерживают парадигму SQL. Они хранят данные в виде ключ-значение. Примеры таких баз - memcached, redis. Обе базы хранят данные в памяти, поэтому доступ к ним очень быстрый. Memcached сам по себе не умеет сохранять данные на диск, а вот Redis умеет, что делает его хорошим кандидатом для хранилища данных. Еще есть memcachedb - распределенное ключ-значение хранилище, которое сохраняет данные на диске, но оно не обновлялось уже почти три года.
В чем же суть ключ-значение хранилища? Фактически вы работаете с ним как с ассоциативным массивом - обращаясь каждый раз к отдельным ключам массива. Давайте поработаем в Редисом из пхп. С установкой Редиса разберитесь сами,
Возьмем в качестве клиента библиотеку predis. Вот простой тестовый скрипт, комментарии добавляю прямо в код:
<?php
require_once(__DIR__ . '/../lib/Predis.php');// подключили библиотеку
require_once(__DIR__ . '/../lib/Predis_Compatibility.php');
$single_server = array( // задали параметры подключения
'host' => '127.0.0.1',
'port' => 6379
);
$redis = new Predis_Client($single_server);// объект для работы с Редисом
$redis->set('library', 'predis');// установили ключ 'library' в значение 'predis'
$retval = $redis->get('library');// получили значение ключа 'library'
var_dump($retval);// посмотрели что получилось
var_dump($redis->expire('library', 100));// установили время жизни ключа 10 сек и посмотрели удачно ли
Хранение данных пользователя
Итак, как же Редис может хранить наши данные о пользователях? Прежде всего, он может хранить строки, как мы уже убедились на примере. А в строку можно сериализовать массив - ряд из БД. Что нибудь вроде такого
$user_id = 101; $key_user = 'user_'.$user_id; $user_data = array( 'login' => 'vasyap', 'password' => 'dzenaum', 'fio' => 'Вася Пупкин', ); $redis->set($key_user, serialize($user_data));// записали сериализованные данные $out = $redis->get($key_user);// получили значение ключа var_dump(unserialize($out)); // получили данные из Редиса
Попробуйте, должно работать.
Можно для каждого поля в $user_data использовать свой ключ, например так
$user_id = 101;
$user_data = array(
'login' => 'vasyap',
'password' => 'dzenaum',
'fio' => 'Вася Пупкин',
);
$redis->set('user:login:'.$user_id, $user_data['login']);
$redis->set('user:password:'.$user_id, $user_data['password']);
$redis->set('user:fio:'.$user_id, $user_data['fio']);
Мне такой подход не очень нравится, так как плодится очень много ключей, которые сложнее обслуживать.
Для хранения данных пользователя можно использовать хеш
$user_id = 101; $key_user = 'user_'.$user_id; $user_data = array( 'login' => 'vasyap', 'password' => 'dzenaum', 'fio' => 'Вася Пупкин', ); $redis->hmset($key_user, $user_data); $ret = $redis->hgetall($key_user); var_dump($ret);
причем в хеше можно обращаться к отдельным ключам. Наверно так удобнее всего.
Уникальность
Как мы можем в Редисе проверить уникальность логина или е-мейла? Перебирать все данные пользователя для ответа на этот вопрос - плохая идея. Решение такое: на каждого пользователя заведем ключ 'user_login_'.$login , где $login реальное значение логина. Для проверки на уникальность будем просто проверять наличие данных с таким ключом.
$redis->set('user_login_'.'ivan', 1);
$redis->set('user_login_'.'olga', 1);
function is_login_exist($login) { // проверка на уникальность
global $redis;
$key_login = 'user_login_'.$login;
$ret = $redis->get($key_login);
return $ret != Null;
}
var_dump(is_login_exist('ivan')); // return true
var_dump(is_login_exist('olga')); // return true
var_dump(is_login_exist('vasyap')); // return false
Уникальный ид
Обеспечить уникальный ид можно с помощью дополнительного ключа и комаyды incr, которая атомарна (на каждое обращение вернет уникальное значение).
function next_user_id() {
global $redis;
$next_user_id_key = 'next_user_id_key';
return $redis->incr($next_user_id_key);
}
echo next_user_id()."\n"; // 1
echo next_user_id()."\n"; // 2
echo next_user_id()."\n"; // 3
