摘要:多线程版本中,和的工作方式和非持久连接的工作方式相同。如果设为默认,一次发出一条命令,有时会返回空数组。
Redis 类和方法
Redis 类
RedisException 类
预定义常量
Redis 类创建Redis客户端
$redis = new Redis();RedisException 类
如果无法访问Redis服务器,phpredis抛出RedisException异常,如Redis服务关闭,Redis主机过载等。除去服务器无法访问的情形(key不存在,或无效命令等),phpredis返回FALSE
预定义常量可用的Redis常量
Redis数据类型,同方法 type 返回值
Redis::REDIS_STRING - String Redis::REDIS_SET - Set Redis::REDIS_LIST - List Redis::REDIS_ZSET - Sorted set Redis::REDIS_HASH - Hash Redis::REDIS_NOT_FOUND - Not found / otherRedis 连接
connect, open - 连接到Redis服务器
pconnect, popen - 连接到Redis服务器(持久连接)
auth - 服务器验证
select - 切换数据库
swapdb - 交换两个数据库
close - 关闭连接
setOption - 设置客户端配置
getOption - 获取客户端配置
ping - 查看服务是否运行
echo - 输出给定字符串
connect, open连接到Redis实例
host: string 域名或unix套接字
port: int 可选,端口号
timeout: float 连接超时时间,秒(可选,默认0,表示无限制)
reverved: 如果指定了retry_interval,该值应为NULL
retry_interval: int 重连延时时间,毫秒(可选)
read_timeout: float 读取key的超时时间,秒(可选,默认0,表示无限制)
boolean: 成功返回TRUE,失败返回FALSE
$redis->connect("127.0.0.1", 6379); $redis->connect("127.0.0.1"); // 默认6379端口 $redis->connect("127.0.0.1", 6379, 2.5); // 2.5s连接超时 $redis->connect("/tmp/redis.sock"); // unix套接字 $redis->connect("127.0.0.1", 6379, 1, NULL,100); // 1s连接超时,100ms延时重连pconnect, popen
连接到Redis实例,或重用pconnect/popen建立的连接
使用close命令或结束请求都不会关闭连接,直到php进程结束。因此,在连接到同一台redis服务器的多台服务器上使用持久连接时,要对大量的FD错误有所防备,尤其在redis服务器端。
持久连接可以通过host + port + timeout或host + persistent_id或unix socket + timeout建立。
该特性不适用于多线程版本。多线程版本中,pconnect和popen的工作方式和非持久连接的工作方式相同。
host: string 域名或unix套接字
port: int 端口号,可选
timeout: float 连接超时时间,秒(可选,默认0,表示无限制)
persistent_id: string 持久连接请求标识
retry_interval: int 重连时间间隔,秒
read_timeout: float 读取key的超时时间,秒(可选,默认0,表示无限制)
boolean: 成功返回TRUE,失败返回FALSE
$redis->pconnect("127.0.0.1", 6379); $redis->pconnect("127.0.0.1"); // 默认端口6379,和上述连接为同一连接 $redis->pconnect("127.0.0.1", 6379, 2.5); // 2.5s超时,新连接 $redis->pconnect("127.0.0.1", 6379, 2.5, "x"); // x作为persistent_id,新连接 $redis->pconnect("/tmp/redis.sock"); // unix套接字,新连接auth
使用密码验证连接,密码以纯文本形式发送。
password: string
boolean: 验证通过返回TRUE,否则返回FALSE
示例$redis->auth("foobared");select
切换到指定数据库
dbindex: int 数据库索引
boolean: 成功返回TRUE,失败返回FALSE
参考 move 方法
swapdb交换两数据库
db1: int
db2: int
boolean: 成功返回TRUE,失败返回FALSE
注意:要求Redis >= 4.0.0
$redis->swapdb(0, 1); // 交换数据库 0 和 1close
断开与Redis实例的连接,除非使用pconnect
setOption设置客户端配置
parameter name
parameter value
boolean: 成功返回TRUE,失败返回FALSE
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); // 不序列化数据 $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); // 使用内置的序列化/反序列化 $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY); // 使用 igBinary 序列化/反序列化 $redis->setOption(Redis::OPT_PREFIX, "myAppName"); // 在所有 key 上使用自定义前缀 /* SCAN 系列命令配置,指示是否获取空的用户输入。如果设为 SCAN_NORETRY (默认),phpredis 一次发出一条 SCAN 命令,有时会返回空数组。如果设为 SCAN_RETRY ,phpredis 会重复发送 SCAN 指令,直到返回 keys 或者 Redis 返回零迭代器 */ $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY); $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);getOption
获取客户端配置
parameter name
parameter value
$redis->getOption(Redis::OPT_SERIALIZER); // 返回 Redis::SERIALIZER_NONE, Redis::SERIALIZER_PHP 或 Redis::SERIALIZER_IGBINARYping
检查连接状态
无
string: 成功返回+PONG,失败时抛出RedisException异常
echo打印字符串
string: string 要输出的字符串
string: 输入的字符串
Redis 服务器bgRewriteAOF - 异步执行一个AOF(append-only file)文件重写操作
bgSave - 在后台异步保存当前数据库的数据到磁盘
config - 获取/设置Redis服务器配置
dbSize - 返回当前数据库的key的数量
flushAll - 删除所有数据库的所有key
flushDb - 删除当前数据库的所有key
info - 获取Redis服务器的各种信息和统计数值
lastSave - 返回最近一次Redis成功将数据保存到磁盘上的时间,以UNIX时间戳格式表示
resetStat - 重置 info 命令中的某些统计数据
save - 同步保存数据到硬盘
slaveOf - 将当前服务器转变为指定服务器的从属服务器
time - 返回当前服务器时间
slowLog - 管理redis的慢日志
bgRewriteAOF异步执行一个AOF(append-only file)文件重写操作
无
boolean: 成功返回TRUE,失败返回FALSE
$redis->bgRewriteAOF();bgSave
在后台异步保存当前数据库的数据到磁盘
无
boolean: 成功返回TRUE,失败返回FALSE。如果正在执行save操作,返回FALSE
$redis->bgSave();config
获取/设置Redis服务器配置
operation: string GET或SET
key: string
value: string 可选(仅针对SET)
array/boolean: GET返回关联数组,SET返回布尔值
$redis->config("GET", "*max-*entries*"); $redis->config("SET", "dir", "/var/run/redis/dumps/");dbSize
返回当前数据库的key的数量
无
int: 当前数据库的key的数量
$count = $redis->dbSize(); echo "Redis has $count keys ";flushAll
删除所有数据库的所有key
无
boolean: 始终返回TRUE
$redis->flushAll();flushDb
删除当前数据库的所有key
无
boolean: 始终返回TRUE
$redis->flushDb();info
获取Redis服务器的各种信息和统计数值
返回Redis服务器信息组成的数组,不传递参数时,返回如下信息:
redis_version
arch_bits
uptime_in_seconds
uptime_in_days
connected_clients
connected_slaves
used_memory
changes_since_last_save
bgsave_in_progress
last_save_time
total_connections_received
total_commands_processed
role
通过传递一系列参数,可以让命令只返回某一部分信息。
option: string 提供给redis的选项(COMMANDSTSTS,CPU等)
$redis->info(); $redis->info("COMMANDSTATS"); // 已执行命令信息 (版本 >= 2.6) $redis->info("CPU"); // CPU信息lastSave
返回最近一次Redis成功将数据保存到磁盘上的时间,以UNIX时间戳格式表示
无
int: UNIX时间戳
$redis->lastSave();resetStat
重置 info 命令中的某些统计数据
清空以下统计信息:
Keyspace hits
Keyspace missed
Number of commands processed
Number of connections received
Number of expired keys
无
boolean: 成功返回TRUE,失败返回FALSE
$redis->resetStat();save
同步保存数据到硬盘
无
boolean: 成功返回TRUE,失败返回FALSE。如果save操作正在执行,返回FALSE
$redis->save();slaveOf
将当前服务器转变为指定服务器的从属服务器
host: string
port: int
不传递参数表示终止从属关系
boolean: 成功返回TRUE,失败返回FALSE
$redis->slaveOf("10.0.1.7", 6379); $redis->slaveOf();time
返回当前服务器时间
无
array: 成功时返回一个关联数组,数组的第一个元素是unix时间戳秒数,第二个元素是微秒数
$redis->time();slowLog
管理redis的慢日志
Operation: string GET、LEN或RESET
Length: int 可选,如果执行SLOWLOG GET命令,可以传递该参数
array/int/boolean:
SLOWLOG返回值取决于执行的操作:
SLOWLOG GET 返回关联数组
SLOWLOG LEN 返回slowLog长度 integer
SLOWLOG RESET 返回Boolean
// 获取10条slowlog记录 $redis->slowLog("get", 10); // 获取默认条数的slowlog记录 $redis->slowLog("get"); // 重置slowlog $redis->slowLog("reset"); // 获取slowlog长度 $redis->slowLog("len");Redis 字符串和 Redis 键 Redis 字符串
append - 追加一个值到key
bitCount - 统计指定位区间上,值为 1 的位的个数
bitOp - 在字符串之间执行按位运算
decr, decrBy - 减少key的值
get - 获取key的值
getBit - 对key所储存的字符串值,获取指定偏移量上的位(bit)
getRange - 返回key中字符串值的子字符串
getSet - 将给定key的值设为value,并返回key的旧值(old value)
incr, incrBy - 增加key的值
incrByFloat - 将key所储存的值加上给定的浮点增量值(increment)
mGet, getMultiple - 获取所有(一个或多个)给定key的值
mSet, mSetNX - 同时设置一个或多个 key-value 对
set - 设置指定key的值
setBit - 对key所储存的字符串值,设置或清除指定偏移量上的位(bit)
setEx, pSetEx - 为key赋值,并设置过期时间
setNx - 只有在key不存在时设置key的值
setRange - 从指定偏移量开始,覆写给定key所储存的字符串值
strLen - 返回key所储存的字符串值的长度
Redis 键del, delete, unlink - 删除key
dump - 序列化给定key,并返回被序列化的值
exists - 检查给定key是否存在
expire, setTimeout, pexpire - 为给定key设置过期时间
expireAt, pexpireAt - 将key的过期时间设置为unix时间戳
keys, getKeys - 查找所有符合给定模式(pattern)的key
scan - 扫描所有key
migrate - 将key从一个Redis实例转移到另一个实例
move - 将当前数据库的key移动到给定的数据库当中
object - 获取key对象信息
persist - 移除key的过期时间,key将持久保持
randomKey - 从当前数据库中随机返回一个key
rename, renameKey - 修改key的名称
renameNx - 仅当新key不存在时,将key改名为新的key名
type - 返回key所储存的值的类型
sort - 对列表、集合或有序集中的元素进行排序
ttl, pttl - 获取key的剩余的过期时间
restore - 用通过 dump 获得的序列化值创建一个key
获取key的值
key: string
string/boolean: key不存在时返回FALSE,否则返回key的值
$redis->get("key");set
设置指定key的值
Key: string
Value: string
int/array: 可选,若传递int,将调用SETEX命令。如果Redis >= 2.6.12,则可以传递扩展选项
boolean: 成功时返回TRUE
$redis->set("key", "value"); // 将调用SETEX方法 $redis->set("key", "value", 10); // 设置key值,如果key不存在,设置10s过期 $redis->set("key", "value", array("nx", "ex" => 10)); // 设置key值,如果key不存在,设置1000ms过期 $redis->set("key", "value", array("xx", "px" => 1000));setEx, pSetEx
为key赋值,并设置过期时间(setEx使用秒数,pSetEx使用毫秒)
Key: string
TTL: int
Value: string
boolean: 成功返回TRUE
$redis->setEx("key", 3600, "value"); // 设置key值,1h过期 $redis->pSetEx("key", 100, "value"); // 设置key值,100ms过期setNx
只有在key不存在时设置key的值
key: string
value: string
boolean: 成功返回TRUE,失败返回FALSE
$redis->setNx("key", "value"); // 返回 TRUE $redis->setNx("key", "value"); // 返回 FALSEdel, delete, unlink
删除key
array/string: keys组成的数组,或多个key: key1 key2 key3 ... keyN
int: 被删除的key数量
$redis->set("key1", "val1"); $redis->set("key2" ,"val2"); $redis->set("key3", "val3"); $redis->set("key4", "val4"); $redis->delete("key1" ,"key2"); // 返回 2 $redis->delete(array("key3", "key4")); // 返回 2 // Redis >= 4.0.0 时可以调用unlink方法 $redis->unlink("key1", "key2"); $redis->unlink(array("key1", "key2"));exists
检查给定key是否存在
key: string
int: 检测的keys中,key存在的数量
$redis->set("key", "value"); $redis->exists("key"); // 1 $redis->exists("NonExistingKey"); // 0 $redis->mSet(["foo" => "foo", "bar" => "bar", "baz" => "baz"]); $redis->exists(["foo", "bar", "barz"]); // 3 $redis->exists("foo", "bar", "baz"); // 3
注意: Redis < 4.0.0时,该方法仅接受一个参数,返回布尔值
incr, incrBykey的值自增 1, 如果传递第二个参数,则作为key的增量
key: string
value: int key的增量(仅对incrBy有效)
int: 自增后的值
$redis->incr("key1"); // 若 key1 不存在,自增前默认为 0 ,然后自增 1 $redis->incr("key1"); // 2 $redis->incr("key1"); // 3 $redis->incr("key1"); // 4 // 将调用INCRBY $redis->incr("key1", 10); // 14 $redis->incr("key1", 10); // 24incrByFloat
将key所储存的值加上给定的浮点增量值
key: string
value: float 增量
float: 自增后的值
$redis->incrByFloat("key1", 1.5); // 1.5 $redis->incrByFloat("key1", 1.5); // 3 $redis->incrByFloat("key1", -1.5); // 1.5 $redis->incrByFloat("key1", 2.5); // 4decr, decrBy
key的值自减 1,如果传递第二个参数,将该参数作为减量
key: string
value: int key的减量(仅对decrBy有效)
int: 自减后的值
$redis->decr("key1"); // key1不存在,初始化为0,然后自减 $redis->decr("key1"); // -2 $redis->decr("key1"); // -3 // 将调用DECRBY $redis->decr("key1", 10); // -13 $redis->decr("key1", 10); // -23mGet, getMultiple
获取所有(一个或多个)给定key的值,如果有一个或多个key不存在,对应的key值为FALSE
keys: array key列表
array: keys对应的值
$redis->set("key1", "value1"); $redis->set("key2", "value2"); $redis->set("key3", "value3"); $redis->mGet(array("key1", "key2", "key3")); // array("value1", "value2", "value3"); $redis->mGet(array("key0", "key1", "key5")); // array("FALSE", "value1", "FALSE");getSet
将给定key的值设为value,并返回key的旧值
Key: string
string: key的旧值
$redis->set("x", "42"); $exValue = $redis->getSet("x", "lol"); // 返回 "42", key 的值替换为 "lol" $newValue = $redis->get("x"); // 返回 "lol"randomKey
从当前数据库中随机返回一个key
无
string: 随机的一个key值
$key = $redis->randomKey(); $surprise = $redis->get($key);move
将当前数据库的key移动到给定的数据库当中
Key: string 待移动的key
dbindex: int 数据库索引
boolean: 成功返回TRUE,失败返回FALSE
$redis->select(0); // 切换到数据库 0 $redis->set("x", "42"); // 设置 x 值为 "42" $redis->move("x", 1); // 移动 x 到数据库 1 $redis->select(1); // 切换到数据库 1 $redis->get("x"); // 返回 "42"rename, renameKey
修改key的名称
srckey: string 旧名称
dstkey: string 新名称
boolean: 成功返回TRUE,失败返回FALSE
$redis->set("x", "42"); $redis->rename("x", "y"); $redis->get("y"); // 42 $redis->get("x"); // FALSErenameNx
仅当新key不存在时,将key改名为新的key名
expire, setTimeout, pexpire为给定key设置过期时间,以秒计(pexpire为毫秒)
Key: string
ttl: int key存活时长
boolean: 成功返回TRUE,失败返回FALSE
$redis->set("x", "42"); $redis->setTimeout("x", 3); // x 在 3s 后过期 sleep(5); $redis->get("x"); // 返回 FALSEexpireAt, pexpireAt
将key的过期时间设置为unix时间戳
Key: string
timestamp: int Unix时间戳,key的过期时间
boolean: 成功返回TRUE,失败返回FALSE
$redis->set("x", "42"); $now = time(NULL); $redis->expireAt("x", $now + 3); // x 在 3s 后过期 sleep(5); $redis->get("x"); // 返回 FALSEkeys, getKeys
查找所有符合给定模式(pattern)的key
pattern: string 使用*作为通配符
array: 与特定模式匹配的key
$allKeys = $redis->keys("*"); // 匹配所有 key $keyWithUserPrefix = $redis->keys("user*");scan
扫描所有key
iterator: int 迭代次数的引用,初始值为NULL
pattern: string 可选,匹配模式
count: int 可选,每次迭代的key的数量
array/boolean: 返回keys数组,如果Redis中key数量为 0,返回FALSE
// 默认不启用 Redis::SCAN_RETRY $it = NULL; do { // 扫描 keys $arr_keys = $redis->scan($it); // 返回值可能为空,预防这种情形 if ($arr_keys !== FALSE) { foreach ($arr_keys as $str_key) { echo "Here is a key: $str_key "; } } } while ($it > 0); echo "No more keys to scan! "; // 启用 Redis::SCAN_RETRY $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); $it = NULL; // 如果返回值为空,phpredis 会再次执行 SCAN,因此不需要检查结果是否为空 while ($arr_keys = $redis->scan($it)) { foreach ($arr_keys as $str_key) { echo "Here is a key: $str_key "; } } echo "No more keys to scan! ";object
获取key对象信息
info: string 需要获取的key信息,可以为下列值:
encoding
refcount
idletime
string/int/boolean: encoding返回string,refcount返回int,如果为idletime,key不存在时返回FALSE
$redis->object("encoding", "l"); // ziplist $redis->object("refcount", "l"); // 1 $redis->object("idletime", "1"); // 400s,精度为10stype
返回key所储存的值的类型
Key: string
string
根据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");append
追加一个值到key
Key: string
Value: string
int: 追加指定值之后,key中字符串的长度
$redis->set("key", "value1"); $redis->append("key", "value2"); // 返回 12 $redis->get("key"); // "value1value"getRange
返回key中字符串值的子字符串
key: string
start: int
end: int
string: 子字符串
$redis->set("key", "string value"); $redis->getRange("key", 0, 5); // "string" $redis->getRange("key", -5, -1); // "value"setRange
从指定偏移量开始,覆写给定key所储存的字符串值
key: string
offset: int
value: string
int: 修改后的字符串长度
$redis->set("key", "Hello world"); $redis->setRange("key", 6, "redis"); // 返回 11 $redis->get("key"); // "Hello redis"strLen
返回key所储存的字符串值的长度
key: string
int
$redis->set("key", "value"); $redis->strLen("key"); // 5getBit
对key所储存的字符串值,获取指定偏移量上的位(bit)
key: string
offset: int
int: 指定位上的值(0 或 1)
$redis->set("key", "x7f"); // 0111 1111 $redis->getBit("key", 0); // 0 $redis->getBit("key", 1); // 1setBit
对key所储存的字符串值,设置或清除指定偏移量上的位(bit)
key: string
offset: int
value: int 1 或 0
int: 0 或 1,设置之前的位值
$redis->set("key", "*"); // ord("*") = 42 = 0x2a = "0010 1010" $redis->setBit("key", 5, 1); // 返回 0 $redis->setBit("key", 7, 1); // 返回 0 $redis->get("key"); // chr(0x2f) = "/" = b("0010 1111")bitOp
在字符串之间执行按位运算
operation: string AND, OR, NOT, XOR
ret_key: string 目标key
key: string
key2...: string
int: 存储在目标key中的字符串长度
bitCount统计指定位区间上,值为 1 的位的个数
key: string
int: 返回key值的所有位中,值为 1 的位的个数
sort对列表、集合或有序集中的元素进行排序
Key: string
Options: array array(key => value, ...) - 可选,使用以下键值对:
"by" => "some_pattern_*", "limit" => array(0, 1), "get" => "some_other_pattern_*" 或 patterns 数组 "sort" => "asc"/"desc", "alpha" => TRUE, "store" => "external-key"
array: key值数组,或存储的元素个数
$redis->delete("s"); $redis->sAdd("s", 5); $redis->sAdd("s", 4); $redis->sAdd("s", 2); $redis->sAdd("s", 1); $redis->sAdd("s", 3); var_dump($redis->sort("s")); // 1, 2, 3, 4, 5 var_dump($redis->sort("s", array("sort" => "desc"))); // 5, 4, 3, 2, 1 var_dump($redis->sort("s", array("sort" => "desc", "store" => "out"))); // (int) 5ttl, pttl
获取key的剩余的过期时间,秒数(ttl),毫秒数(pptl)
Key: string
int: key的过期时间。如果key没有过期时间,返回-1;key不存在,返回-2
$redis->ttl("key");persist
移除key的过期时间,key将持久保持
Key: string
boolean: 成功移除过期时间,返回TRUE;key不存在,或没有过期时间,返回FALSE;
$redis->persist("key");mSet, mSetNx
同时设置一个或多个 key-value 对
Pairs: array array(key => value, ...)
boolean: 成功返回TRUE,失败返回FALSE
$redis->mSet(array("key0" => "value0", "key1" => "value1")); var_dump($redis->get("key0")); // string(6) "value0" var_dump($redis->get("key1")); // string(6) "value1"dump
序列化给定key,并返回被序列化的值
key string
string/boolean: 返回序列化之后的值,如果key不存在,返回FALSE
$redis->set("foo", "bar"); $val = $redis->dump("foo");restore
用通过 dump 获得的序列化值创建一个key
key: string
ttl: integer key的存活时间,为 0 时不设置过期时间
value: string dump获得的序列化值
$redis->set("foo", "bar"); $val = $redis->dump("foo"); $redis->restore("bar", 0, $val); // "bar"的值不等于"foo"的值migrate
将key从一个Redis实例转移到另一个实例
host:string 目标域名
port: int 要连接的TCP端口
key(s): string/array
destination-db: int 目标数据库
timeout: int 转移超时时间
copy: boolean 可选,是否复制
replace: boolean 是否替换
$redis->migrate("backup", 6379, "foo", 0, 3600); $redis->migrate("backup", 6379, "foo", 0, 3600, true, true); // 复制和替换 $redis->migrate("backup", 6379, "foo", 0, 3600, false, true); // 仅替换 // 转移多个 key,要求 Redis >= 3.0.6 $redis->migrate("backup", 6379, ["key1", "key2", "key3"], 0, 3600);Redis 哈希
hDel - 删除一个或多个哈希表字段
hExists - 查看哈希表中,指定的字段是否存在
hGet - 获取存储在哈希表中指定字段的值
hGetAll - 获取在哈希表中的所有字段和值
hIncrBy - 为哈希表中的指定字段的整数值加上增量
hIncrByFloat - 为哈希表中的指定字段的浮点数值加上增量
hKeys - 获取哈希表中的所有字段名
hLen - 获取哈希表中字段的数量
hMGet - 获取所有给定字段的值
hMSet - 同时为哈希表中的多个字段赋值
hSet - 为哈希表中的一个字段赋值
hSetNx - 只有在字段不存在时,设置哈希表字段的值
hVals - 获取哈希表中所有值
hScan - 迭代哈希表中的键值对
hStrLen - 获取哈希表中,字段值的长度
hSet为哈希表中的一个字段赋值
key: string
hashkey: string
value: string
int/false: 如果字段是哈希表中的一个新建字段,并且值设置成功,返回 1 。 如果哈希表中域字段已经存在且旧值已被新值覆盖,返回 0 。出错时返回FALSE
$redis->delete("h"); $redis->hSet("h", "key1", "hello"); // 返回 1,"key` => "hello" $redis->hGet("h", "key1"); // 返回 "hello" $redis->hSet("h", "key1", "plop"); // 替换字段值,返回 0 $redis->hGet("h", "key1"); // 返回 "plop"hSetNx
只有在字段不存在时,设置哈希表字段的值
boolean: 成功返回TRUE,字段已存在则返回FALSE
$redis->delete("h"); $redis->hSetNx("h", "key1", "hello"); // TRUE $redis->hSetNx("h", "key1", "world"); // FALSEhGet
获取存储在哈希表中指定字段的值,如果哈希表或key不存在,返回FALSE
key: string
hashKey: string
string/boolean: 成功时返回字段的值,失败返回FALSE
hLen获取哈希表中字段的数量
key: string
int: 哈希表中字段的数量,如果key不存在或非哈希表,返回FALSE
$redis->delete("h"); $redis->hSet("h", "key1", "hello"); $redis->hSet("h", "key2", "plop"); $redis->hLen("h"); // 返回 2hDel
删除一个或多个哈希表字段,如果哈希表或key不存在,返回FALSE
key: string
hashKey1: string
hashKey2: string
int/boolean: 被删除的字段数量,key不存在时返回 0,key非哈希则返回FALSE
hKeys获取哈希表中的所有字段名,返回字符串数组
Key: string
array: 哈希表中所有字段名称组成的数组,类似PHP中的array_keys()
$redis->delete("h"); $redis->hSet("h", "a", "x"); $redis->hSet("h", "b", "y"); $redis->hSet("h", "c", "z"); $redis->hSet("h", "d", "t"); var_dump($redis->hKeys("h")); /* 输出 array(4) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> string(1) "c" [3]=> string(1) "d" } */
字段的顺序是随机的,对应于Redis集合的内部排序
hVals获取哈希表中所有值,返回字符串数组
Key: string
array: 哈希表中所有字段值组成的数组,类似PHP中的array_values()
$redis->delete("h"); $redis->hSet("h", "a", "x"); $redis->hSet("h", "b", "y"); $redis->hSet("h", "c", "z"); $redis->hSet("h", "d", "t"); var_dump($redis->hVals("h")); /* 输出 array(4) { [0]=> string(1) "x" [1]=> string(1) "y" [2]=> string(1) "z" [3]=> string(1) "t" } */
字段的顺序是随机的,对应于Redis集合的内部排序
hGetAll获取在哈希表中的所有字段和值
Key: string
array: 关联数组,哈希表的字段名称为键名,字段值为键值
$redis->delete("h"); $redis->hSet("h", "a", "x"); $redis->hSet("h", "b", "y"); $redis->hSet("h", "c", "z"); $redis->hSet("h", "d", "t"); var_dump($reids->hGetAll("h")); /* 输出 array(4) { ["a"]=> string(1) "x" ["b"]=> string(1) "y" ["c"]=> string(1) "z" ["d"]=> string(1) "t" } */hExists
查看哈希表中,指定的字段是否存在
key: string
memberKey: string
boolean: 若哈希表中,指定字段存在,返回TRUE,否则返回FALSE
$redis->hSet("h", "a", "x"); $redis->hExists("h", "a"); // TRUE $redis->hExists("h", "NonExistingKey"); // FALSEhIncrBy
为哈希表中的指定字段的整数值加上增量
key: string
member: string
value: int 字段的增量
int: 自增后的字段值
$redis->delete("h"); $redis->hIncrBy("h", "x", 2); // 返回 2,h[x] = 2 $redis->hIncrBy("h", "x", 1); // h[x] = 2 + 1,返回 2hIncrByFloat
为哈希表中的指定字段的浮点数值加上增量
key: string
member: string
value: float 字段的浮点值增量
float: 自增后的字段值
$redis->delete("h"); $redis->hIncrByFloat("h", "x", 1.5); // 返回 1.5,h[x] = 1.5 $redis->hIncrByFloat("h", "x", 1.5); // 返回 3.0,h[x] = 3.0 $redis->hIncrByFloat("h", "x", -3.0); // 返回 0.0,h[x] = 0.0hMSet
同时为哈希表中的多个字段赋值,非字符串值将被转换为字符串,NULL值转化为空字符串
key: string
members: array key => value数组
boolean
$redis->delete("user:1"); $redis->hMSet("user:1", array("name" => "Joe", "salary" => 2000)); $redis->hIncrBy("user:1", "salary", 100);hMGet
获取所有给定字段的值
key: string
memberKeys array
array: 字段名称为键名,字段值为键值的数组
$redis->delete("h"); $redis->hSet("h", "field1", "value1"); $redis->hSet("h", "field2", "value2"); $redis->hMGet("h", ["field1", "field2"]); // 返回 array("field1" => "value1", "field2" => "value2")hScan
迭代哈希表中的键值对
key: string
iterator: int 迭代次数的引用
pattern: string 可选,匹配模式
count: int 每次返回的字段数
array: 与给定模式匹配的元素组成的数组
$it = NULL; // 在迭代完成之前,不返回空值 $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); while ($arr_keys = $redis->hScan("hash", $it)) { foreach ($arr_keys as $str_field => $str_value) { echo "$str_field => $str_value "; } }hStrLen
获取哈希表中,字段值的长度
key: string
field: string
int: 字段值的长度,哈希表或字段不存在时,返回 0
Redis 列表blPop, brPop - 移出并获取列表的第一个/最后一个元素
bRPopLPush - 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它
lIndex, lGet - 通过索引获取列表中的元素
lInsert - 在列表的元素前或者后插入元素
lLen, lSize - 获取列表长度
lPop - 移出并获取列表的第一个元素
lPush - 将一个或多个值插入到列表头部
lPushX - 将一个值插入到已存在的列表头部
lRange, lGetRange - 获取列表指定范围内的元素
lRem, lRemove - 移除列表元素
lSet - 通过索引设置列表元素的值
lTrim, listTrim - 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
rPop - 移除并获取列表最后一个元素
rPopLPush - 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
rPush - 在列表中添加一个或多个值
rPushX - 为已存在的列表添加值
blPop, brPop移出并获取列表的第一个/最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
keys: array 包含列表中key的数组
timeout: int 超时时间
或
key: string
key2: string
key3: string
...
keyn: string
timeout: int 超时时间
array: array("listName", "element")
// 非阻塞 $redis->lPush("key1", "A"); $redis->delete("key2"); $redis->blPop("key1", "key2", 10); // array("key1", "A") // 或 $redis->blPop(["key1", "key2"], 10); // array("key1", "A") $redis->brPop("key1", "key2", 10); // array("key1", "A"); // 或 $redis->brPop(["key1", "key2"], 10); // array("key1", "A") // 阻塞 // 进程 1 $redis->delete("key1"); $redis->blPop("key1", 10); // 阻塞 10s // 进程 2 $redis->lPush("key1", "A") // 进程 1 // 返回 array("key1", "A")bRPopLPush
rPopLPush的阻塞版本,第三个参数为等待超时时间
srcKey: string
dstKey: string
timeout: int 超时时间
string/boolean: 返回被移除的元素,等待超时则返回FALSE
lIndex, lGet返回列表中,指定位置的元素
0 指第一个元素,1 指第二个元素...
-1 指最后一个元素,-2 指倒数第二个元素
如果key未指向列表,或索引值无效,返回FALSE
key: string
index: int
string/boolean: 返回指定索引处的元素。如果索引对应的元素不存在,或非字符串类型,返回FALSE
$redis->rPush("key1", "A"); $redis->rPush("key1" ,"B"); $redis->rPush("key1", "C"); // key1 => ["A", "B", "C"] $redis->lGet("key1", 0); // "A" $redis->lGet("key1", -1); // "C" $redis->lGet("key1", 10); // FALSElInsert
在列表的元素前或者后插入元素
当列表不存在,或指定元素不存在与列表中时,不执行任何操作
key: string
position: string Redis::BEFORE | Redis::AFTER
pivot: string
value: string
int: 返回插入操作完成之后,列表的长度。如果没有找到指定元素,返回 -1
$redis->delete("key1"); $redis->lInsert("key1", Redis::AFTER, "A", "X"); // 0 $redis->lPush("key1", "A"); $redis->lPush("key1", "B"); $redis->lPush("key1", "C"); $redis->lInsert("key1", Redis::BEFORE, "C", "X"); // 4 $redis->lRange("key1", 0, -1); // array("A", "B", "X", "C") $redis->lInsert("key1", Redis::AFTER, "C", "Y"); // 5 $redis->lRange("key1", 0, -1); // array("A", "B", "X", "C", "Y") $redis->lInsert("key1", Redis::AFTER, "W", "value"); // -1lPop
移出并获取列表的第一个元素
key: string
string/boolean: 返回列表的第一个元素,失败时(空列表)返回FALSE
$redis->rPush("key1", "A"); $redis->rPush("key1", "B"); $redis->rPush("key1", "C"); // key1 => ["A", "B", "C"] $redis->lPop("key1"); // key1 => ["B", "C"]lPush
将一个或多个值插入到列表头部。如果key不存在,一个空列表会被创建并执行lPush操作。当key存在但不是列表类型时,返回FALSE
key: string
value: string 要插入到列表中的字符串
int: 返回执行插入操作后,列表的长度。失败时返回FALSE
$redis->delete("key1"); $redis->lPush("key1", "C"); // 返回 1 $redis->lPush("key1", "B"); // 返回 2 $redis->lPush("key1", "A"); // 返回 3 // key1 现在指向列表: ["A", "B", "C"]lPushX
将一个值插入到已存在的列表头部
key: string
value: string 要插入到列表中的字符串
int: 返回执行插入操作后,列表的长度。失败时返回FALSE
$redis->delete("key1"); $redis->lPushX("key1", "A"); // 返回 0 $redis->lPush("key1", "A"); // 返回 1 $redis->lPushX("key1", "B"); // 返回 2 $redis->lPushX("key1", "C"); // 返回 3 // key1 现在指向列表: ["A", "B", "C"]lRange, lGetRange
返回列表中指定区间内的元素,区间以偏移量start和end指定。
其中 0 表示列表的第一个元素, 1 表示列表的第二个元素...
以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素...
key: string
start: int
end: int
array: 包含指定区间内元素的数组
$redis->rPush("key1", "A"); $redis->rPush("key1", "B"); $redis->rPush("key1", "C"); $redis->lRange("key1", 0, -1); // array("A", "B", "C")lRem, lRemove
根据参数count的值,移除列表中与参数value相等的元素。
如果count = 0,移除表中所有与value相等的值;
如果count < 0,从表尾开始向表头搜索,移除与value相等的元素,数量为count的绝对值;
如果count > 0,从表头开始向表尾搜索,移除与value相等的元素,数量为count
key: string
value: string
count: int
int/boolean: 返回被移除元素的数量。列表不存在时返回FALSE
$redis->lPush("key1", "A"); $redis->lPush("key1", "B"); $redis->lPush("key1", "C"); $redis->lPush("key1", "A"); $redis->lPush("key1", "A"); $redis->lRange("key1", 0, -1); // array("A", "A", "C", "B", "A") $redis->lRem("key1", "A", 2); // 2 $redis->lRange("key1", 0, -1); // array("C", "B", "A")lSet
通过索引设置列表元素的值
key: string
index: int
value: string
boolean: 操作成功返回TRUE。如果索引超出范围,或者key不指向列表,返回FALSE
$redis->rPush("key1", "A"); $redis->rPush("key1", "B"); $redis->rPush("key1", "C"); // key1 => ["A", "B", "C"] $redis->lGet("key1", 0); // "A" $redis->lSet("key1", 0, "X"); $redis->lGet("key1", 0); // "X"lTrim, listTrim
对一个列表进行修剪(trim),让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
key: string
start: int
stop: int
array: 返回列表中剩余元素组成的数组。如果key值不是列表,返回FALSE
$redis->rPush("key1", "A"); $redis->rPush("key1", "B"); $redis->rPush("key1", "C"); $redis->lRange("key1", 0, -1); // array("A", "B", "C") $redis->lTrim("key1", 0, 1); $redis->lRange("key1", 0, -1); // array("A", "B")rPop
移除并获取列表最后一个元素
key: string
string: 返回被移除的元素。失败(列表为空)返回FALSE
$redis->rPush("key1", "A"); $redis->rPush("key1", "B"); $redis->rPush("key1", "C"); // key1 => ["A", "B", "C"] $redis->rPop("key1"); // key1 => ["A", "B"]rPopLPush
移除列表的最后一个元素,并将该元素添加到另一个列表并返回
srcKey: string
dstKey: string
string: 返回被移除的元素。失败返回FALSE
$redis->delete("x", "y"); $redis->lPush("x", "abc"); $redis->lPush("x", "def"); $redis->lPush("y", "123"); $redis->lPush("y", "456"); var_dump($redis->rPopLPush("x", "y")); var_dump($redis->lRange("x", 0, -1)); var_dump($redis->lRange("y", 0, -1)); /* 输出 string(3) "abc" array(1) { [0]=> string(3) "def" } array(3) { [0]=> string(3) "abc" [1]=> string(3) "456" [2]=> string(3) "123" } */rPush
将一个或多个值插入到列表的尾部(最右边),如果列表不存在,一个空列表会被创建并执行rPush操作。 当列表存在但不是列表类型时,返回FALSE
key: string
value: string 要插入到列表的字符串
int: 执行插入操作后,列表的长度。失败返回FALSE
$redis->delete("key1"); $redis->rPush("key1", "A"); // 返回 1 $redis->rPush("key1", "B"); // 返回 2 $redis->rPush("key1", "C"); // 返回 3 // key1 => ["A", "B", "C"]rPushX
将一个值插入到已存在的列表尾部(最右边)。失败返回FALSE
key: string
value: string 要插入到列表的字符串
int: 执行插入操作后,列表的长度。失败返回FALSE
$redis->delete("key1"); $redis->rPushX("key1", "A"); // 返回 0 $redis->rPush("key1", "A"); // 返回 1 $redis->rPushX("key1", "B"); // 返回 2 $redis->rPushX("key1", "C"); // 返回 3 // key1 => ["A", "B", "C"]lLen, lSize
返回列表的长度。
如果列表key不存在或为空列表,返回 0 。如果key不是列表类型,返回FALSE
Key: string
int: 返回列表的长度。如果key不是列表,返回FALSE
$redis->rPush("key1", "A"); $redis->rPush("key1", "B"); $redis->rPush("key1", "C"); // key1 => ["A", "B", "C"] $redis->lSize("key1"); // 3 $redis->rPop("key1"); $redis->lSize("key1"); // 2Redis 集合
sAdd - 向集合添加一个或多个成员
sCard, sSize - 获取集合的成员数
sDiff - 返回给定所有集合的差集
sDiffStore - 返回给定所有集合的差集并存储在key中
sInter - 返回给定所有集合的交集
sInterStore - 返回给定所有集合的交集并存储在key中
sIsMember, sContains - 判断元素是否是集合的成员
sMembers, sGetMembers - 返回集合中的所有成员
sMove - 将元素从一个集合移动到另一个集合
sPop - 移除并返回集合中的一个或多个随机元素
sRandMember - 返回集合中一个或多个随机元素
sRem, sRemove - 移除集合中一个或多个成员
sUnion - 返回所有给定集合的并集
sUnionStore - 所有给定集合的并集存储在key集合中
sScan - 迭代集合中的元素
sAdd将一个或多个成员元素加入到集合中。如果元素已存在于集合中,返回FALSE
key: string
value: string
int: 返回被添加到集合中的新元素的数量
$redis->sAdd("key1", "member1"); // 1, key1 => {"member"} $redis->sAdd("key1", "member2", "member3"); // 2, key1 => {"member1", "member2", "member3"} $redis->sAdd("key1", "member2"); // 0, key1 => {"member1", "member2", "member3"}sCard, sSize
返回集合中元素的数量
key: string
int: 返回集合中元素的数量。 当集合key不存在时,返回 0
$redis->sAdd("key1", "member1"); $redis->sAdd("key1", "member2"); $redis->sAdd("key1", "member3"); // key1 => {"member1", "member2", "member3"} $redis->sCard("key1"); // 3 $redis->sCard("keyX); // 0sDiff
返回给定集合之间的差集
Keys: string key, key2, ..., keyN 指向集合的任意数量的key
array: 第一个集合与其他所有集合差集元素组成的数组
$redis->delete("s0", "s1", "s2"); $redis->sAdd("s0", "1"); $redis->sAdd("s0", "2"); $redis->sAdd("s0", "3"); $redis->sAdd("s0", "4"); $redis->sAdd("s1", "1"); $redis->sAdd("s2", "3"); var_dump($redis->sDiff("s0", "s1", "s2")); /* 返回所有存在于 s0,但既不存在于 s1 也不存在于 s2 中的元素 array(2) { [0]=> string(1) "4" [1]=> string(1) "2" } */sDiffStore
将给定集合之间的差集存储在指定的集合中
dstKey: string 用于存储差集的key
keys: string key1, key2, ..., keyN 指向集合的任意数量的key
int: 返回差集中的元素数量。如果某个key不存在,返回FALSE
$redis->delete("s0", "s1", "s2"); $redis->sAdd("s0", "1"); $redis->sAdd("s0", "2"); $redis->sAdd("s0", "3"); $redis->sAdd("s0", "4"); $redis->sAdd("s1", "1"); $redis->sAdd("s2", "3"); var_dump($redis->sDiffStore("dst", "s0", "s1", "s2")); var_dump($redis->sMembers("dst")); /* 返回所有存在于 s0,但既不存在于 s1 也不存在于 s2 中的元素 int(2) array(2) { [0]=> string(1) "4" [1]=> string(1) "2" } */sInter
返回给定所有给定集合的交集
当给定集合当中有一个空集时,结果也为空集。如果某个key不存在,返回FALSE
keys: string key1, key2, ..., keyN: string,指向集合的任意数量的key
array: 返回交集成员组成的数组。如果交集为空,返回空数组
$redis->sAdd("key1", "val1"); $redis->sAdd("key1", "val2"); $redis->sAdd("key1", "val3"); $redis->sAdd("key1", "val4"); $redis->sAdd("key2", "val3"); $redis->sAdd("key2", "val4"); $redis->sAdd("key3", "val3"); $redis->sAdd("key3", "val4"); var_dump($redis->sInter("key1", "key2", "key3")); /* 输出 array(2) { [0]=> string(4) "val4" [1]=> string(4) "val3" } */sInterStore
将给定集合之间的交集存储在指定的集合中
dstKey: string 用于存储交集的key
keys: string key, key2, ..., keyN 指向集合的任意数量的key
int: 返回存储交集的集合的元素数量。如果某个key不存在,返回FALSE
$redis->sAdd("key1", "val1"); $redis->sAdd("key1", "val2"); $redis->sAdd("key1", "val3"); $redis->sAdd("key1", "val4"); $redis->sAdd("key2", "val3"); $redis->sAdd("key2", "val4"); $redis->sAdd("key3", "val3"); $redis->sAdd("key3", "val4"); var_dump($redis->sInterStore("output", "key1", "key2", "key3")); var_dump($redis->sMembers("output")); /* 输出 int(2) array(2) { [0]=> string(4) "val4" [1]=> string(4) "val3" } */sIsMember, sContains
判断成员元素是否是集合的成员
key: string
value: string
boolean: 如果元素是集合的成员,返回TRUE。否则返回FALSE
$redis->sAdd("key1", "member1"); $redis->sAdd("key1", "member2"); $redis->sAdd("key1", "member3"); // key1 => {"member1", "member2", "member3"} $redis->sIsMember("key1", "member1"); // TRUE $redis->sIsMember("key1", "memberX"); // FALSEsMembers, sGetMembers
返回集合中的所有的成员
Key: string
array: 集合中的所有成员组成的数组
$redis->delete("s"); $redis->sAdd("s", "a"); $redis->sAdd("s", "b"); $redis->sAdd("s", "a"); $redis->sAdd("s", "c"); var_dump($redis->sMembers("s")); /* 输出 array(3) { [0]=> string(1) "c" [1]=> string(1) "a" [2]=> string(1) "b" } */
顺序随机,对应于Redis集合内部的排序
sMove将指定元素从当前集合移动到目标集合
srcKey: string
dstKey: string
member: string
boolean: 操作成功返回TRUE。如果当前key或目标key不存在,或元素不存在于当前key中,返回FALSE
$redis->sAdd("key1", "member11"); $redis->sAdd("key1", "member12"); $redis->sAdd("key1", "member13"); // key1 => {"member11", "member12", "member13"} $redis->sAdd("key2", "member21"); $redis->sAdd("key2", "member22"); // key2 => {"member21", "member22"} $redis->sMove("key1", "key2", "member13"); /* key1 => {"member11", "member12"} key2 => {"member21", "member22", "member13"} */sPop
移除集合中的一个或多个随机元素,返回移除的元素
key: string
count: int 可选
string/boolean: 被移除的元素。集合不存在或为空,返回FALSE
array/boolean: 被移除元素组成的数组。集合不存在时,返回空数组。key不是集合,返回FALSE
$redis->sAdd("key1", "member1"); $redis->sAdd("key1", "member2"); $redis->sAdd("key1", "member3"); // key1 => {"member3", "member1", "member2"} $redis->sPop("key1"); // "member1", key1 => {"member3", "member2"} $redis->sPop("key1"); // "member3", key1 => {"member2"} // 传递 count 参数 $redis->sAdd("key2", "member1", "member2", "member3"); $redis->sPop("key2", 3); // 返回所有成员,顺序随机sRandMember
返回集合中的一个随机元素
key: string
count: int 可选
string/array/boolean:
不提供count参数:返回一个随机元素(String)。
提供count参数:如果count为正数,且小于集合基数,返回一个包含count个元素的数组,数组中的元素各不相同。如果count大于等于集合基数,那么返回整个集合。如果count为负数,返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为count的绝对值。集合不存在,返回FALSE
$redis->sAdd("key1", "member1"); $redis->sAdd("key1", "member2"); $redis->sAdd("key1", "member3"); // key1 => {"member3", "member1", "member2"} // 无 count 参数 $redis->sRandMember("key1"); // "member1", key1 => {"member3", "member1", "member2"} $redis->sRandMember("key1"); // "member3", key1 => {"member3", "member1", "member2"} // 有 count 参数 $redis->sRandMember("key1", 3); // 返回集合所有元
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/29612.html
摘要:发布,新增队列驱动,缓存驱动移动至,使用老版本的需要修改中缓存驱动加载位置。目前支持根据获取配置的基本读写等。和可以继续使用自带的驱动,两者互不影响。下一步如有需要可以继续完善这两部分的驱动。 欢迎关注我的博客 http://targetliu.com Lumen的确是一款适合做API,速度很快的框架。但是在项目中使用Redis时发现Lumen默认使用的 predis/predis 会...
摘要:背景安装完之后,需要安装扩展,才能让操作本机有多个版本,安装过程中遇到的坑分享一下。四问题修复已修复,但是原因可能不太准确编译报错最初以为是多个版本生成问题,采用指定版本,指定位置。 背景:安装完redis之后,需要安装phpredis扩展,才能让php操作redis;本机有多个php版本,安装过程中遇到的坑分享一下。 一 下载 git上下载redis的扩展包 git clone ht...
摘要:下载我用的浏览器右击,点击复制链接地址,在目录下,使用网络下载解压下载好的文件配置使用命令行查找位置进解压好的目录里配置,在当前目录输入以下四条命令记下目录,配置需要用到,也可以用命令查找查看安装信息查看配置在文件里添加两条信息存储扩展 1、下载phpredis https://github.com/phpredis/p... 我用的chrome浏览器右击tar.gz,点击复制链接地址...
摘要:下载,地址下载完成得到移动到目录中进入目录解压得到文件夹,将文件夹改名为进入文件夹执行若未安装,则会报错需要先安装若未安装,则另外百度安装的方法安装完之后,再执行,接着执行下面的代码执行执行由于点几开始本身关闭了对 下载php-redis,地址:https://nodeload.github.com/n... 下载完成得到phpredis-master.zip 移动到/usr/loca...
阅读 1388·2021-10-11 10:58
阅读 1471·2021-09-04 16:41
阅读 669·2019-08-30 15:55
阅读 798·2019-08-29 18:46
阅读 3133·2019-08-29 14:05
阅读 3524·2019-08-26 14:00
阅读 2448·2019-08-26 13:53
阅读 3164·2019-08-26 13:29