Redis的数据类型
类型 简介 特性 场景
String(字符串) 二进制安全 可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M —
Hash(字典) 键值对集合,即编程语言中的Map类型 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去) 存储、读取、修改用户属性
List(列表) 链表(双向链表) 增删快,提供了操作某一段元素的API 1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列
Set(集合) 哈希表实现,元素不重复 1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
Sorted Set(有序集合) 将Set中的元素增加一个权重参数score,元素按score有序排列 数据插入集合时,已经进行天然排序 1、排行榜 2、带权重的消息队列
Redis启动的命令
启动redis
连接后可以使用PING命令检测redis服务器是否启动
Redis keys命令
1.DEL key
该命令用于在 key 存在时删除 key
如果删除成功返回 (integer) 1,删除失败返回 (integer) 0
2.DUMP key
序列化给定 key ,并返回被序列化的值,
如果 key 不存在,那么返回 nil . 否则,返回序列化之后的值
3.EXISTS key
检查给定 key 是否存在
若 key 存在返回 1 ,否则返回 0 。
4.EXPIRE key seconds
为给定 key 设置过期时间,以秒计.
设置成功返回 1 . 当 key 不存在或者不能为 key 设置过期时间时返回 0 .
5.EXPIREAT key timestamp
EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳
Ps:为什么使用UNIX时间戳?
在现在的系统中经常遇到跨数据库的应用开发,在数据库系统中不同的数据库对与时间类型却有不同解释,比如ORACLE的date和MYSQL里面的date就不能直接兼容转换,数据方面还可以使用数据迁移工具进行转换,但是对与应用来说那就是灾难.
为了实现跨平台在应用系统中记录时间的时候我们就可以使用记录UNIX时间戳的方法做到跨平台性
6.PEXPIRE key milliseconds
设置 key 的过期时间以毫秒计
7.KEYS pattern
查找所有符合给定模式( pattern)的 key ,返回符合给定模式的 key 列表 (Array)
*:匹配0个或多个字符
?:匹配一个字符
[a,b,…]:匹配其中的某个字符
8.MOVE key db
将当前数据库的 key 移动到给定的数据库 db 当中
移动成功返回 1 ,失败则返回 0 .
9.PERSIST key
移除 key 的过期时间,key 将持久保持
当过期时间移除成功时,返回 1 。 如果 key 不存在或 key 没有设置过期时间,返回 0
10.TTL key
以秒为单位,返回给定 key 的剩余生存时间
当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间
11.RENAME key newkey
修改 key 的名称
改名成功时提示 OK ,失败时候返回一个错误,
当 OLD_KEY_NAME 和 NEW_KEY_NAME 相同,或者 OLD_KEY_NAME 不存在时,返回1个错误。 当 NEW_KEY_NAME 已经存在时, RENAME 命令将覆盖旧值。
12.RENAMEX key newkey
仅当 newkey 不存在时,将 key 改名为 newkey
13.TYPE key
返回 key 所储存的值的类型
数据类型有:
none (key不存在)
string (字符串)
list (列表)
set (集合)
zset (有序集)
hash (哈希表)
14.RANDOMKEY
从当前数据库中随机返回一个 key
当数据库不为空时,返回一个 key 。 当数据库为空时,返回 nil (windows 系统返回 null
Redis 字符串(String) 命令
1.GETRANGE key start end
Redis Getrange 命令用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)
2.GETSET key value
将给定 key 的值设为 value ,并返回 key 的旧值,当 key 没有旧值时,即 key 不存在时,返回 nil .
3.GETBIT key offset
对 key 所储存的字符串值,获取指定偏移量上的位(bit)
当偏移量 OFFSET 比字符串值的长度大,或者 key 不存在时,返回 0
4.MGET key1[key2…]
获取所有(一个或多个)给定 key 的值
返回所有(一个或多个)给定 key 的值,如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil
5.SETRANGE key offset value
用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始
6.STRLEN key
返回 key 所储存的字符串值的长度
返回字符串值的长度。 当 key 不存在时,返回 0
7.MSET key value[key1 value…]
同时设置一个或多个 key-value 对
8.MSETNX key value[key value…]
同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
8.INCRBY key increment
将 key 所储存的值加上给定的增量值
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。
如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
本操作的值限制在 64 位(bit)有符号数字表示之内
9.INCRBYFLOAT key increment
将 key 所储存的值加上给定的浮点增量值
10.DECR key
将 key 中储存的数字值减一
11.DECRBY key decrement
key 所储存的值减去给定的减量值
12.APPEND key value
如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾
如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。
如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样
Redis 哈希(hash) 命令
1.HDEL key field[field1]
删除一个或多个哈希表字段
返回被成功删除字段的数量,不包括被忽略的字段.
2.HEXISTS key filed
查看哈希表 key 中,指定的字段是否存在
如果哈希表含有给定字段,返回 1 。 如果哈希表不含有给定字段,或 key 不存在,返回 0
3.HGET key field
获取存储在哈希表中指定字段的值
4.HGETALL key
获取在哈希表中指定 key 的所有字段和值
5.HINCRBY key field increment
为哈希表 key 中的指定字段的整数值加上增量 increment
6.HINCRBYFLOAT key field increment
为哈希表 key 中的指定字段的浮点数值加上增量 increment
7.HKEYS key
获取所有哈希表中的字段
8.HLEN key
获取哈希表中字段的数量
9.HVALS key
获取哈希表中所有值
Redis 列表(List)命令
1.LPUSH key value1[value2]
将一个或多个值插入到列表头部
Redis Lpush 命令将一个或多个值插入到列表头部。 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。 当 key 存在但不是列表类型时,返回一个错误
2.RPUSH key value1[value2]
将一个或多个值插入到列表的尾部(最右边)。
如果列表不存在,一个空列表会被创建并执行 RPUSH 操作。 当列表存在但不是列表类型时,返回一个错误。
3.BLPOP key1[key2] timeout
Redis Blpop 命令移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
如果列表为空,返回一个 nil 。 否则,返回一个含有两个元素的列表,第一个元素是被弹出元素所属的 key ,第二个元素是被弹出元素的值。
4.BRPOP key1[key2] timeout
移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
5.LINDEX key index
Lindex 命令用于通过索引获取列表中的元素。你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推
6.LINSERT key BEFORE/AFTER pivot value
在列表的元素前或者后插入元素。当指定元素不存在于列表中时,不执行任何操作。
当列表不存在时,被视为空列表,不执行任何操作。
如果 key 不是列表类型,返回一个错误。
7.LLEN key
返回列表的长度。 如果列表 key 不存在,则 key 被解释为一个空列表,返回 0 。 如果 key 不是列表类型,返回一个错误。
8.LPOP key
移除并返回列表的第一个元素
9.LRANGE key start stop
返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推
10.LREM key count value
Redis Lrem 根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。
COUNT 的值可以是以下几种:
count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
count = 0 : 移除表中所有与 VALUE 相等的值。
11.LTRIM key start stop
让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
Redis 集合(set)命令
1.SADD key member1[member2]
Redis Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
假如集合 key 不存在,则创建一个只包含添加的元素作成员的集合。
当集合 key 不是集合类型时,返回一个错误
2.SCARD KEY_NAME
返回集合中元素的数量
3.SDIFF key1[key2]
返回第一个集合与其他集合之间的差异,也可以认为说第一个集合中独有的元素。不存在的集合 key 将视为空集
4.SDIFFSTROE destination key1[key2]
返回给定所有集合的差集并存储在 destination 中
5.SINTER key1[key2]
返回给定所有给定集合的交集。 不存在的集合 key 被视为空集。 当给定集合当中有一个空集时,结果也为空集
6.SINTERSTORE destination key1[key2]
将给定集合之间的交集存储在指定的集合中。如果指定的集合已经存在,则将其覆盖
7.SISMEMBER key member
判断成员元素是否是集合的成员
8.SMEMBERS key
返回集合中的所有成员
9.SMOVE source destination member
将 member 元素从 source 集合移动到 destination 集合
10.SPOP key [count]
移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素
11.SRANDMERBER key [count]
返回集合中一个或多个随机数
12.SREM key member1[member2]
移除集合中的一个或多个成员元素,不存在的成员元素会被忽略
13.SUNION ket1[key2]
返回给定集合的并集。不存在的集合 key 被视为空集
Redis 有序集合(sorted set)命令
1.ZADD key score1 member1[score2 member2]
将一个或多个成员元素及其分数值加入到有序集当中。
如果某个成员已经是有序集的成员,那么更新这个成员的分数值,并通过重新插入这个成员元素,来保证该成员在正确的位置上。
2.ZCARD key
获取有序集合的成员数
3.ZCOUNT key min max
计算有序集合中指定分数区间的成员数量
4.ZINCRBY key increment member
有序集合中对指定成员的分数加上增量 increment
5.ZINTERSTORE destination numkeys key[key]
计算给定的一个或多个有序集的交集,其中给定 key 的数量必须以 numkeys 参数指定,并将该交集(结果集)储存到 destination 。
默认情况下,结果集中某个成员的分数值是所有给定集下该成员分数值之和。
6.ZLEXCOUNT key min max
计算有序集合中指定字典区间内成员数量,找指定字典区间内成员时,分为两个判定状态,首先找符合第一个条件的成员,找到后从当前位置开始按集合顺序判定成员是否满足第二个条件(此时不再考虑第一个条件),如果发现成员不满足查找会直接结束。
7.ZRANGE key start stop [withscores]
通过索引返回有序集中,指定区间内的成员。
其中成员的位置按分数值递增(从小到大)来排序。
具有相同分数值的成员按字典序来排列。
8.ZRANGEBYLEX key min max [LIMIT offset count]
通过字典区间返回有序集合的成员
9.ZRAGEBYSCORE key min max[WITHSCORES]
通过分数返回有序集合指定区间内的成员
10.ZRANK key member
返回有序集合中指定成员的索引
11…ZREM key member[member…]
移除有序集合中的一个或多个成员
12.ZREMRANGEBYLEX key min max
移除有序集合中给定的字典区间的所有成员
13.ZREMRANGEBYRANK key min max
移除有序集合中给定的排名区间的所有成员
14…ZREMRANGEBYSCORE key min max
移除有序集合中给定的分数区间的所有成员
Redis HyperLogLog
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
命令
1.PFADD key element[element]
将所有元素参数添加到 HyperLogLog 数据结构中
2.PFCOUNT key[key…]
返回给定 HyperLogLog 的基数估算值
3.PFMERGE destkey sourcekey[sourcekey…]
将多个 HyperLogLog 合并为一个 HyperLogLog
Redis 发布订阅
发布订阅(pub/sub)是一种消息通信模式,主要目的是解除消息发布者和消息订阅者之间的耦合。redis作为一个pub/sub的server,在订阅者和发布者之间启动了消息路由的功能。订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型。redis将信息类型成为通道(channel).当发布者通过publish命令向redis server 发送特定类型的信息时,订阅该信息类型的全部client都会受到此消息。
首先需要接收端先监听某频道:
subscribe 频道名
subscribe news
其次发布端发布消息:
publish 频道名 内容
publish news “hello”’
Client1接受到信息
Redis发布订阅常用命令
1PSUBSCRIBE pattern [pattern …]
订阅一个或多个符合给定模式的频道,假设客户端同时订阅了某种模式和符合该模式的某个频道,那么发送给这个频道的消息将被客户端接收到两次,只不过这两条消息的类型不同,一个是message类型,一个是pmessage类型,但其内容相同。
2SUBSCRIBE channel [channel …] 订阅给定的一个或多个频道的信息
3 PUBSUB subcommand [argument [argument …]] 查看订阅与发布系统状态。
4 PUBLISH channel message 将信息发送到指定的频道。
5 PUNSUBSCRIBE [pattern [pattern …]] 退订所有给定模式的频道。
6 UNSUBSCRIBE [channel [channel …]] 只退订给定的频道。
Redis 事务
Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
批量操作在发送 EXEC 命令前被放入队列缓存。
收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行会经历以下三个阶段:
开始事务
命令入队
执行事务
Redis 事务命令
1.DISCARD
取消事务,放弃执行事务块内的所有命令
2.EXEC
执行所有事务块内的命令
3.MULTI
标记一个事务块的开始
4.WATCH key[key…]
用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
5.UNWATCH
用于取消 WATCH 命令对所有 key 的监视
Redis 脚本
1 EVAL script numkeys key [key …] arg [arg …]
script: 参数是一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数。
numkeys: 用于指定键名参数的个数。
key [key …]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
arg [arg …]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)
2 EVALSHA sha1 numkeys key [key …] arg [arg …]
Redis Evalsha 命令根据给定的 sha1 校验码,执行缓存在服务器中的脚本。
将脚本缓存到服务器的操作可以通过 SCRIPT LOAD 命令进行。
这个命令的其他地方,比如参数的传入方式,都和 EVAL 命令一样
3 SCRIPT EXISTS script [script …]
查看指定的脚本是否已经被保存在缓存当中。
4 SCRIPT FLUSH
从脚本缓存中移除所有脚本。
5 SCRIPT KILL
杀死当前正在运行的 Lua 脚本。
6 SCRIPT LOAD script
Redis Script Load 命令用于将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
EVAL 命令也会将脚本添加到脚本缓存中,但是它会立即对输入的脚本进行求值。
如果给定的脚本已经在缓存里面了,那么不执行任何操作。
在脚本被加入到缓存之后,通过 EVALSHA 命令,可以使用脚本的 SHA1 校验和来调用这个脚本。
脚本可以在缓存中保留无限长的时间,直到执行 SCRIPT FLUSH 为止
将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
Redis 连接命令
1.AUTH password
验证密码是否正确
2.ECHO message
打印字符串
3.PING
查看服务是否运行
4.QUIT
关闭当前连接
5.SELECT index
切换到指定的数据库
Redis 服务器
1 BGREWRITEAOF
异步执行一个 AOF(AppendOnly File) 文件重写操作
2 BGSAVE
在后台异步保存当前数据库的数据到磁盘
3 CLIENT KILL [ip:port] [ID client-id]
关闭客户端连接
4 CLIENT LIST
获取连接到服务器的客户端连接列表
5 CLIENT GETNAME
获取连接的名称
6 CLIENT PAUSE timeout
在指定时间内终止运行来自客户端的命令
7 CLIENT SETNAME connection-name
设置当前连接的名称
8 CLUSTER SLOTS
获取集群节点的映射数组
9 COMMAND
获取 Redis 命令详情数组
10 COMMAND COUNT
获取 Redis 命令总数
11 COMMAND GETKEYS
获取给定命令的所有键
12 TIME
返回当前服务器时间
13 COMMAND INFO command-name [command-name …]
获取指定 Redis 命令描述的数组
14 CONFIG GET parameter
获取指定配置参数的值
15 CONFIG REWRITE
对启动 Redis 服务器时所指定的 redis.conf 配置文件进行改写
16 CONFIG SET parameter value
修改 redis 配置参数,无需重启
17 CONFIG RESETSTAT
重置 INFO 命令中的某些统计数据
18 DBSIZE
返回当前数据库的 key 的数量
19 DEBUG OBJECT key
获取 key 的调试信息
20 DEBUG SEGFAULT
让 Redis 服务崩溃
21 FLUSHALL
删除所有数据库的所有key
22 FLUSHDB
删除当前数据库的所有key
23 INFO [section]
获取 Redis 服务器的各种信息和统计数值
24 LASTSAVE
返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示
25 MONITOR
实时打印出 Redis 服务器接收到的命令,调试用
26 ROLE
返回主从实例所属的角色
27 SAVE
同步保存数据到硬盘
28 SHUTDOWN [NOSAVE] [SAVE]
异步保存数据到硬盘,并关闭服务器
29 SLAVEOF host port
将当前服务器转变为指定服务器的从属服务器(slave server)
30 SLOWLOG subcommand [argument]
管理 redis 的慢日志
31 SYNC
用于复制功能(replication)的内部命令
Redis GEO
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作
1.GEOADD key longitude latitude member [longitude latitude member …]
geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中
2.GEOPOS key member [member …]
geopos 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil
3.GEODIST key member1 member2 [m|km|ft|mi]
geodist 用于返回两个给定位置之间的距离
4.georadius
根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
5.georadiusbymember
根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
6.geohash
返回一个或多个位置对象的 geohash 值。
Redis 安全
我们可以通过 redis 的配置文件设置密码参数,这样客户端连接到 redis 服务就需要密码验证,这样可以让你的 redis 服务更安全
Redis SCAN命令
SCAN cursor [MATCH pattern] [COUNT count]
SCAN 命令及其相关的 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都用于增量地迭代(incrementally iterate)一集元素(a collection of elements):
SCAN 命令用于迭代当前数据库中的数据库键。
SSCAN 命令用于迭代集合键中的元素。
HSCAN 命令用于迭代哈希键中的键值对。
ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)。
以上列出的四个命令都支持增量式迭代, 它们每次执行都只会返回少量元素, 所以这些命令可以用于生产环境, 而不会出现像 KEYS 命令、 SMEMBERS 命令带来的问题 —— 当 KEYS 命令被用于处理一个大的数据库时, 又或者 SMEMBERS 命令被用于处理一个大的集合键时, 它们可能会阻塞服务器达数秒之久。
不过, 增量式迭代命令也不是没有缺点的: 举个例子, 使用 SMEMBERS 命令可以返回集合键当前包含的所有元素, 但是对于 SCAN 这类增量式迭代命令来说, 因为在对键进行增量式迭代的过程中, 键可能会被修改, 所以增量式迭代命令只能对被返回的元素提供有限的保证 。
SCAN 、 SSCAN 、 HSCAN 和 ZSCAN 四个命令的工作方式都非常相似,但是要记住:
SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一个参数总是一个数据库键。
而 SCAN 命令则不需要在第一个参数提供任何数据库键 —— 因为它迭代的是当前数据库中的所有数据库键。
SCAN命令的基本用法
SCAN 命令是一个基于游标的迭代器(cursor based iterator): SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。
以下是一个 SCAN 命令的迭代过程示例:
redis 127.0.0.1:6379> scan 0
- “17”
-
- “key:12”
- “key:8”
- “key:4”
- “key:14”
- “key:16”
- “key:17”
- “key:15”
- “key:10”
- “key:3”
- “key:7”
- “key:1”
redis 127.0.0.1:6379> scan 17
- “0”
-
- “key:5”
- “key:18”
- “key:0”
- “key:2”
- “key:19”
- “key:13”
- “key:6”
- “key:9”
- “key:11”
在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。
第二次迭代使用的是第一次迭代时返回的游标, 也即是命令回复第一个元素的值 —— 17 。
从上面的示例可以看到, SCAN 命令的回复是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 而第二个数组元素则是一个数组, 这个数组中包含了所有被迭代的元素。
在第二次调用 SCAN 命令时, 命令返回了游标 0 , 这表示迭代已经结束, 整个数据集(collection)已经被完整遍历过了。
以 0 作为游标开始一次新的迭代, 一直调用 SCAN 命令, 直到命令返回游标 0 , 我们称这个过程为一次完整遍历(full iteration)。
SCAN命令的保证
SCAN 命令, 以及其他增量式迭代命令, 在进行完整遍历的情况下可以为用户带来以下保证: 从完整遍历开始直到完整遍历结束期间, 一直存在于数据集内的所有元素都会被完整遍历返回; 这意味着, 如果有一个元素, 它从遍历开始直到遍历结束期间都存在于被遍历的数据集当中, 那么 SCAN 命令总会在某次迭代中将这个元素返回给用户。
然而因为增量式命令仅仅使用游标来记录迭代状态, 所以这些命令带有以下缺点:
同一个元素可能会被返回多次。 处理重复元素的工作交由应用程序负责, 比如说, 可以考虑将迭代返回的元素仅仅用于可以安全地重复执行多次的操作上。
如果一个元素是在迭代过程中被添加到数据集的, 又或者是在迭代过程中从数据集中被删除的, 那么这个元素可能会被返回, 也可能不会, 这是未定义的(undefined)。
scan命令每次执行返回的元素数量
增量式迭代命令并不保证每次执行都返回某个给定数量的元素。
增量式命令甚至可能会返回零个元素, 但只要命令返回的游标不是 0 , 应用程序就不应该将迭代视作结束。
不过命令返回的元素数量总是符合一定规则的, 在实际中:
对于一个大数据集来说, 增量式迭代命令每次最多可能会返回数十个元素;
而对于一个足够小的数据集来说, 如果这个数据集的底层表示为编码数据结构(encoded data structure,适用于是小集合键、小哈希键和小有序集合键), 那么增量迭代命令将在一次调用中返回数据集中的所有元素。
最后, 用户可以通过增量式迭代命令提供的 COUNT 选项来指定每次迭代返回元素的最大值。
COUNT选项
虽然增量式迭代命令不保证每次迭代所返回的元素数量, 但我们可以使用 COUNT 选项, 对命令的行为进行一定程度上的调整。
基本上, COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。
虽然 COUNT 选项只是对增量式迭代命令的一种提示, 但是在大多数情况下, 这种提示都是有效的。
COUNT 参数的默认值为 10 。
在迭代一个足够大的、由哈希表实现的数据库、集合键、哈希键或者有序集合键时, 如果用户没有使用 MATCH 选项, 那么命令返回的元素数量通常和 COUNT 选项指定的一样, 或者比 COUNT 选项指定的数量稍多一些。
在迭代一个编码为整数集合(intset,一个只由整数值构成的小集合)、 或者编码为压缩列表(ziplist,由不同值构成的一个小哈希或者一个小有序集合)时, 增量式迭代命令通常会无视 COUNT 选项指定的值, 在第一次迭代就将数据集包含的所有元素都返回给用户。
并非每次迭代都要使用相同的 COUNT 值。
用户可以在每次迭代中按自己的需要随意改变 COUNT 值, 只要记得将上次迭代返回的游标用到下次迭代里面就可以了。
MATCH选项
和 KEYS 命令一样, 增量式迭代命令也可以通过提供一个 glob 风格的模式参数, 让命令只返回和给定模式相匹配的元素, 这一点可以通过在执行增量式迭代命令时, 通过给定 MATCH 参数来实现。
以下是一个使用 MATCH 选项进行迭代的示例:
redis 127.0.0.1:6379> sadd myset 1 2 3 foo foobar feelsgood
(integer) 6
redis 127.0.0.1:6379> sscan myset 0 match f*
- “0”
-
- “foo”
- “feelsgood”
- “foobar”
需要注意的是, 对元素的模式匹配工作是在命令从数据集中取出元素之后, 向客户端返回元素之前的这段时间内进行的, 所以如果被迭代的数据集中只有少量元素和模式相匹配, 那么迭代命令或许会在多次执行中都不返回任何元素。
以下是这种情况的一个例子:
redis 127.0.0.1:6379> scan 0 MATCH 11
- “288”
-
- “key:911”
redis 127.0.0.1:6379> scan 288 MATCH 11
- “224”
- (empty list or set)
redis 127.0.0.1:6379> scan 224 MATCH 11
- “80”
- (empty list or set)
redis 127.0.0.1:6379> scan 80 MATCH 11
- “176”
- (empty list or set)
redis 127.0.0.1:6379> scan 176 MATCH 11 COUNT 1000
- “0”
-
- “key:611”
- “key:711”
- “key:118”
- “key:117”
- “key:311”
- “key:112”
- “key:111”
- “key:110”
- “key:113”
- “key:211”
- “key:411”
- “key:115”
- “key:116”
- “key:114”
- “key:119”
- “key:811”
- “key:511”
- “key:11”
如你所见, 以上的大部分迭代都不返回任何元素。
在最后一次迭代, 我们通过将 COUNT 选项的参数设置为 1000 , 强制命令为本次迭代扫描更多元素, 从而使得命令返回的元素也变多了。
并发执行多个迭代
在同一时间, 可以有任意多个客户端对同一数据集进行迭代, 客户端每次执行迭代都需要传入一个游标, 并在迭代执行之后获得一个新的游标, 而这个游标就包含了迭代的所有状态, 因此, 服务器无须为迭代记录任何状态。
中途停止迭代
因为迭代的所有状态都保存在游标里面, 而服务器无须为迭代保存任何状态, 所以客户端可以在中途停止一个迭代, 而无须对服务器进行任何通知。
即使有任意数量的迭代在中途停止, 也不会产生任何问题。
使用错误的游标进行增量迭代
使用间断的、负数、超出范围或者其他非正常的游标来执行增量式迭代并不会造成服务器崩溃, 但可能会让命令产生未定义的行为。
未定义行为指的是, 增量式命令对返回值所做的保证可能会不再为真。
只有两种游标是合法的:
1.在开始一个新的迭代时, 游标必须为 0 。
2.增量式迭代命令在执行之后返回的, 用于延续迭代过程的游标。
迭代终结的保证
增量式迭代命令所使用的算法只保证在数据集的大小有界的情况下, 迭代才会停止, 换句话说, 如果被迭代数据集的大小不断地增长的话, 增量式迭代命令可能永远也无法完成一次完整迭代。
从直觉上可以看出, 当一个数据集不断地变大时, 想要访问这个数据集中的所有元素就需要做越来越多的工作, 能否结束一个迭代取决于用户执行迭代的速度是否比数据集增长的速度更快。
时间复杂度:
增量式迭代命令每次执行的复杂度为 O(1) , 对数据集进行一次完整迭代的复杂度为 O(N) , 其中 N 为数据集中的元素数量。
返回值:
SCAN 命令、 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都返回一个包含两个元素的 multi-bulk 回复: 回复的第一个元素是字符串表示的无符号 64 位整数(游标), 回复的第二个元素是另一个 multi-bulk 回复, 这个 multi-bulk 回复包含了本次被迭代的元素。
SCAN 命令返回的每个元素都是一个数据库键。
SSCAN 命令返回的每个元素都是一个集合成员。
HSCAN 命令返回的每个元素都是一个键值对,一个键值对由一个键和一个值组成。
ZSCAN 命令返回的每个元素都是一个有序集合元素,一个有序集合元素由一个成员(member)和一个分值(score)组成。
Redis初步学习体会
redis是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API。他支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。他支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合),他提供许多操作命令,能够便捷的对各种数据类型进行操作。Redis还具有发布订阅(pub/sub)的功能,可以将不同的客户端进行通信。Redis 还具有事务这个概念,能一次执行多个命令。Redis也具有编写脚本的功能,可以避免很多重复的工作,Redis还可以通过管道技术来提高服务的吸能。