redis 基础

[TOC]

开启 redis 扩展

官方文档

  • php.ini
[redis]
extension=redis
redis.pconnect.pooling_enabled = 1

相关命令

redis 类

$redis = new Redis();
$redis = new Redis([
    'host' => '127.0.0.1',
    'port' => 6379,
    'connectTimeout' => 2.5,
    'auth' => ['root', 'password'],
    'ssl' => ['verify_peer' => false],
]);
$key = 'key1';

连接

ini_set('default_socket_timeout', -1); // 设置php不断开连接

$redis->connect('127.0.0.1', 6379);

$redis->pconnect('127.0.0.1', 6379);
$redis->pconnect('/tmp/redis.sock'); // 持久性连接,php-fpm进程结束之前一直复用

账号密码

/* Authenticate with the password 'foobared' */
$redis->auth('foobared');

/* Authenticate with the username 'phpredis', and password 'haxx00r' */
$redis->auth(['phpredis', 'haxx00r']);

/* Authenticate with the password 'foobared' */
$redis->auth(['foobared']);

/* You can also use an associative array specifying user and pass */
$redis->auth(['user' => 'phpredis', 'pass' => 'phpredis']);
$redis->auth(['pass' => 'phpredis']);

数据库选择

$redis->select(0);

设置统一前缀

$redis->setOption(Redis::OPT_PREFIX, 'myAppName:'); // use custom prefix on all keys

序列化

$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE);     // Don't serialize data
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);      // Use built-in serialize/unserialize
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY); // Use igBinary serialize/unserialize
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_MSGPACK);  // Use msgpack serialize/unserialize
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_JSON); 

keys 数量

 $redis->dbSize();

清空所有数据库

$redis->flushAll();

清空当前数据库

$redis->flushDb();

同步持久化

$redis->save();

获取 key 类型

所有类型
string: Redis::REDIS_STRING
set: Redis::REDIS_SET

list: Redis::REDIS_LIST
zset: Redis::REDIS_ZSET
hash: Redis::REDIS_HASH
other: Redis::REDIS_NOT_FOUND

$redis->type('key');

获取过期时间

ps: If the key has no ttl, -1 will be returned, and -2 if the key doesn't exist

$redis->ttl('key'); // seconds
$redis->pttl('key'); // milliseconds

事务

mulit

命令块作为单个事务运行

$ret = $redis->multi()
    ->set('key1', 'val1')
    ->get('key1')
    ->set('key2', 'val2')
    ->get('key2')
    ->exec();
PIPELINE

只是将更快地传输到服务器,但没有任何原子性保证

$ret = $redis->pipeline()
    ->set('key1', 'val1')
    ->get('key1')
    ->set('key2', 'val2')
    ->get('key2')
    ->exec();
执行或取消
$redis->exec(); // 执行
$redis->discard(); // 取消
watch

在 watch 和 exec 执行之间,如果发现监听的值发生变化,则执行失败

$redis->watch('x');
$ret = $redis->multi()
    ->incr('x')
    ->exec(); // return true or false

脚本

script
$redis->script('load', $script);
$redis->script('flush');
$redis->script('kill');
$redis->script('exists', $script1, [$script2, $script3, ...]);
eval

Parameters

  • script string.
  • args array, optional.
  • num_keys int, optional. KEYS参数的个数 args.length - key 为 ARGV 参数的个数
$redis->eval("return 1");

  • eval 参数的格式
EVAL script numkeys key [key ...] arg [arg ...]

eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 arg1 arg2 arg3

  1. "key1"
  2. "key2"
  3. "arg1"
  4. "arg2"
  5. "arg3"
lua 脚本
        $script = <<<LUA
local interval_milliseconds = tonumber(ARGV[1])
redis.call('set', KEYS[1], 2)
redis.call('pexpire', KEYS[1], interval_milliseconds)
redis.call('decr', KEYS[1])
local current = redis.call('get', KEYS[1])
local ttl = redis.call('ttl', KEYS[1])
return {current,ttl}
LUA;

$redis->script('load', $script);
$ret = $redis->eval($script, [$key, 1], 1);

string

添加
$redis->set($key, 20); // 设置
// Will set the key, if it doesn't exist, with a ttl of 10 seconds
$redis->set($key, 'value', ['nx', 'ex'=>10]);
// Will set a key, if it does exist, with a ttl of 1000 milliseconds
$redis->set('key', 'value', ['nx', 'px'=>1000]);
// Set the string value in argument as value of the key if the key doesn't already exist in the database
$redis->setNx($key, 'value');

$redis->incr($key, 2); // 自增2
$redis->decr($key, 2); // 自减2
$redis->incr('key1', 1); /* key1 didn't exists, set to 0 before the increment, ex = -1 */

// 追加内容
$redis->set('key', 'value1');
$redis->append('key', 'value2'); /* 12 */
$redis->get('key'); /* 'value1value2' */
获取
$redis->get($key); // 获取
$redis->mGet(['key1', 'key2', 'key3']); // ['value1', 'value2', 'value3'];

// 获取部分内容
$redis->set('key', 'string value');
$redis->getRange('key', 0, 5); /* 'string' */
$redis->getRange('key', -5, -1); /* 'value' */

// 获取并设置
$redis->set('x', '42');
$exValue = $redis->getSet('x', 'lol'); // return '42', replaces x by 'lol'
删除

// 删除
$redis->del($key, 'key2'); /* return 2 */
$redis->del([$key, 'key4']); /* return 2 */
其它
// 重命名
$redis->set('x', '42');
$redis->rename('x', 'y');
$redis->get('y');   // → 42

// 存在
$redis->exists('key');
过期时间
$redis->expire($key, 3);    // x will disappear in 3 seconds.
$now = time(NULL); // current timestamp
$redis->expireAt('x', $now + 3);

hash

新增
$redis->hSet('key', 'field', 'value');
$redis->hMSet('key', ['field2' => 'value2', 'field3' => 'value3']);
获取
$redis->hGet('key', 'field'); /* returns "value" */
$redis->hMGet('key', ['field', 'field2']);
$redis->hKeys('key') // ['field', 'filed2', 'field3']
$redis->hVals('key') // ['value', 'value2', 'value3']
$redis->hGetAll('key') // ['field' => 'value', 'field2' => 'value2', 'field3' => 'value3']
删除
$redis->hDel('key', 'field');
$redis->hDel('key', 'field', 'filed2');
其它
$redis->hExists('key', 'field');

list 列表

新增
$redis->lPush('key1', 'A'); // left push
$redis->rPush('key1', 'B'); // right push
获取
$redis->lIndex('key1', 0); // 获取 list 索引
$redis->lGet('key1', 0); // 获取 list 的值
$redis->lLen('key1'); // 获取 list 长度
弹出
$redis->lPop('key1'); // left pop
$redis->rPop('key1'); // right pop

Sets 集合(value唯一)

新增
$redis->sAdd('key1', 'member1', 'member2', 'member3'); /* 3, 'key1' => {'member1', 'member2', 'member3'}*/
获取
$redis->sCard('key1'); /*获取 set 长度*/
$redis->sDiff('s0', 's1', 's2') // 取差集
$redis->sMembers('key1') // ['member1', 'member2', 'member3']
删除
$redis->sPop('key1', 2); // 随机弹出2个元素
$redis->sRem('key1', 'member2', 'member3'); // 删除

Sorted sets(有序集合)

每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序

新增
$redis->zAdd('key1', 1, 'member1', 'member2', 'member3'); /* 'key1' => {'member1', 'member2', 'member3'}*/
$redis->zAdd('key1', 2, 'member4'); /* 3, 'key1' => {'member1', 'member2', 'member3', 'member4'}*/
获取
$redis->zCard('key1'); /*获取 set 长度*/
$redis->zScore('key', 'val2'); // 获取元素的 score

$redis->zAdd('key', 0, 'val0');
$redis->zAdd('key', 2, 'val2');
$redis->zAdd('key', 10, 'val10');

$redis->zRange('key1', 0, -1); //  ['val0', 'val2', 'val10'] Parameters index start end

$redis->zRangeByScore('key', 0, 3); /* 根据 score 获取 ['val0', 'val2'] */ Parameters index start_score end_score

$redis->zRangeByScore('key', '-inf', '+inf', ['withscores' => TRUE]); /* ['val0' => 0, 'val2' => 2, 'val10' => 10] */
弹出或删除
$redis->zPopMin('key1', 2); // 弹出最低分数的2个元素
$redis->zPopMax('key1', 2); // 弹出最高分数的2个元素
$redis->zRem('key1', 'member2', 'member3'); // 删除

Streams

主要用于消息队列(MQ,Message Queue)

分组
$obj_redis->xGroup('HELP');
$obj_redis->xGroup('CREATE', $str_key, $str_group, $str_msg_id, [$boo_mkstream]);
$obj_redis->xGroup('SETID', $str_key, $str_group, $str_msg_id);
$obj_redis->xGroup('DESTROY', $str_key, $str_group);
$obj_redis->xGroup('DELCONSUMER', $str_key, $str_group, $str_consumer_name);

$obj_redis->xGroup('CREATE', 'mystream', 'mygroup', 0);
新增消息

消息 message ID,我们使用 *表示由 redis 生成,可以自定义,但是要自己保证递增性

$obj_redis->xAdd('mystream', "*", ['field' => 'value']); // return The added message ID, example: '1530063064286-0'
标记为已处理
$obj_redis->xAck($stream, $group, $arr_messages);

$obj_redis->xAck('stream', 'group1', ['1530063064286-0', '1530063064286-1']);
删除消息
$obj_redis->xDel($str_key, $arr_ids);

$obj_redis->xDel('mystream', ['1530115304877-0', '1530115305731-0']);
获取消息
$obj_redis->xRead($arr_streams [, $i_count, $i_block]);
$obj_redis->xRead(['stream1' => '1535222584555-0', 'stream2' => '1535222584555-0']);

$obj_redis->xReadGroup($str_group, $str_consumer, $arr_streams [, $i_count, $i_block]);
$obj_redis->xReadGroup('mygroup', 'consumer1', ['s1' => 0, 's2' => 0]);
获取消息列表
/* Get everything in this stream */
$obj_redis->xRange('mystream', '-', '+');

/* Only the first two messages */
$obj_redis->xRange('mystream', '-', '+', 2);

Pub/sub

subscribe 订阅
$redis = new Redis();
$redis->connect('192.168.1.62', 6379);
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1); // redis方式设置不超时

$redis->subscribe(['chan', 'chan2'], function($redis, $chan, $msg) {
    echo $msg . PHP_EOL;
});
psubscribe 批量订阅

模糊匹配

$redis->psubscribe(['my*'], function($redis, $pattern, $chan, $msg) {
      echo "Pattern: $pattern\n";
      echo "Channel: $chan\n";
      echo "Payload: $msg\n";
});
publish 发布
$redis = new Redis();
$redis->connect('192.168.1.62', 6379);
$redis->publish('chan', 'hello, world!'); // send message.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容