string 字符串
命令 | 行为 | 返回值 | 使用示例(略去回调函数) |
---|---|---|---|
set | 设置存储在单个键和值 | OK | set(‘key’, ‘value’) |
mset | 设置多个键和值 | OK | mset a1 python a2 java a3 c++ |
get | 获取单个键和值 | value/null | get(‘key’) |
mget | 获取多个键和值 | mget a1 a2 a3 | |
append | 将字符追加到指定key值的末尾 | “python27” | append a1 27 |
keys * | 查看所有键名 | ||
keys a* | 查看以小写字母a开头的所有键名 | ||
keys a[0-9] | 查看以a0~a9范围的所有键名 | ||
exists a1 | 判断键名是否存在,存在返回1,不存在返回0 | 0/1 | |
del | 删除存储在给定键中的值(任意类型) | 1/0 | del(‘key’) |
incrby | 将键存储的值加上整数increment | incrby(‘key’, increment) | |
decrby | 将键存储的值减去整数increment | decrby(‘key’, increment) | |
incrbyfloat | 将键存储的值加上浮点数increment | incrbyfloat(‘key’, increment) | |
getrange | 获取指定键的index范围内的所有字符组成的子串 | getrange(‘key’, ‘start-index’, ‘end-index’) | |
setrange | 将指定键值从指定偏移量开始的子串设为指定值 | setrange(‘key’, ‘offset’, ‘new-string’) |
list 列表
命令 | 行为 | 返回值 | 使用示例(略去回调函数) |
---|---|---|---|
lpush | 从左侧(前面)插入数据 | 当前列表长度 | lpush 列表名 值1 值2 值3… |
rpush | 从左侧(前面)插入数据 | 当前列表长度 | rpush 列表名 值1 值2 值3… |
lrange | 查询列表数据 | array | lrange ‘key’ 起始下标 结束下标->>lrange ‘key’ 0 -1 (返回所有值) |
linsert | 在指定位置的前后插入新的元素 (前before 后after) | 当前列表长度 | linsert ‘key’ before 指定值 新的元素 / linsert ‘key’ after 指定值 新的元素 |
lset | 修改指定下标的元素 | OK | lset 键名 元素下标 要修改成的数据 |
lrem | 键名 删除的次数 要删除的数据/删除的次数,数字表示删除多少个,正符号表示从左起,负号表示从右起 | lrem lst 1 b 删除lst中左边起1个b/lrem lst -2 b 删除lst中右边起2个b/如果要删除lst中所有的a 则 lrem lst 0 a | |
ltrim | 截取列表某区间的数据 | ltrim(‘key’, ‘start’, ‘end’)>>ltrim lst 0 4 (截取lst列表里边,0~4 5个数据) | |
lindex | 获取列表在给定位置上的单个元素 | lindex(‘key’, 1) | |
lpop | 从列表左端弹出一个值,并返回被弹出的值 | lpop(‘key’) | |
rpop | 从列表右端弹出一个值,并返回被弹出的值 | rpop(‘key’) |
set 集合
命令 | 行为 | 返回值 | 使用示例(略去回调函数) |
---|---|---|---|
sadd | 将给定元素添加到集合 | 插入元素数量 | sadd 键名 值1 值2 值3 |
smembers | 获取无序集合中的所有元素 | array(无序) | smembers 键名 |
sismember | 检查给定的元素是否存在于集合中 | 1/0 | sismember(‘key’, ‘value’) |
srem | 删除无序集合中的某个元素 | 1/0 | srem 键名 值 |
scard | 返回集合包含的元素的数量 | scard(‘key’) | |
spop | 随机地移除集合中的一个元素,并返回此元素 | spop(‘key’) | |
smove | 集合元素的迁移 | smove(‘source-key’, ‘dest-key’, ‘item’) | |
sdiff | 返回那些存在于第一个集合,但不存在于其他集合的元素(差集) | sdiff(‘key1’, ‘key2’[, ‘key3’, …]) | |
sdiffstore | 将sdiff操作的结果存储到指定的键中 | sdiffstore(‘dest-key’, ‘key1’, ‘key2’ [,‘key3’ ,…]) | |
sinter | 返回那些同事存在于所有集合中的元素(交集) | sinter(‘key1’, ‘key2’[, ‘key3’, …]) | |
sinterstore | 将sinter操作的结果存储到指定的键中 | sinterstore(‘dest-key’, ‘key1’, ‘key2’ [,‘key3’ ,…]) | |
sunion | 返回那些至少存在于一个集合中的元素(并集) | sunion(‘key1’, ‘key2’[, ‘key3’, …]) | |
sunionstore | 将sunion操作的结果存储到指定的键中 | sunionstore(‘dest-key’, ‘key1’, ‘key2’ [,‘key3’ ,…]) |
hash
命令 | 行为 | 返回值 | 使用示例(略去回调函数) |
---|---|---|---|
hsett | 设置单个键属性 | 1(新增)/0(更新) | hset 键名 属性名 值 |
hmset | 设置多个键属性 | OK | 键名 属性名1 值1 属性名2 值2 |
hget | 获取指定散列键的值 | hget 键名 属性名 | |
hmget | 从散列里面获取一个或多个键的值 | array | hmget 键名 属性名1 属性名2 |
hgetall | 获取散列包含的键值对 | json hgetall(‘hash-key’) | |
hdel | 删除hash数据 | hdel 键名 属性名 (可以接空格写多个属性名,表示删除多个属性和值) | |
hlen | 返回散列包含的键值对数量 | hlen(‘hash-key’) | |
hexists | 检查给定键是否在散列中 | 1/0 | hexists(‘hash-key’, ‘sub-key’) |
hkeys | 查看的是这个键里的所有属性名 | array | |
hvals | 获取某个键里边所有属性的值 | array | hmget 键名 属性名1 属性名2 |
hincrby | 将存储的键值以指定增量增加 | 返回增长后的值 | hincrby(‘hash-key’, ‘sub-key’, increment) |
hincrbyfloat | 将存储的键值以指定浮点数增加 |
zset 有序集合
命令 | 行为 | 返回值 | 使用示例(略去回调函数) |
---|---|---|---|
zadd | 将一个带有给定分支的成员添加到有序集合中 | zadd 键名 权重1 值1 权重2 值2 权重3 值3 | |
zrange | 根据元素在有序排列中的位置,从中取出元素 | zrange 键名 起始下标,结束下标 >>zrange 键名 0 -1 | |
zrangebyscore | 获取某key指定权重区间的数据 | zrangebyscore 键名 起始权重 结束权重 >>zrangebyscore names2 4 5 获取权重在4到5的元素 | |
zscore | 获取有序集合中元素的权重值 | 权重值 | zscore 键名 元素 |
zrem | 删除指定元素 | 0/1 | |
zremrangebyscore | 删除权重在某个范围内的元素 | 被删除的个数 | zremrangebyscore ‘key’ 5 6 删除某key权重在5到6之间的元素 |
zcard | 获取一个有序集合中的成员数量 | 有序集的元素个数 | zcard(‘key’) |
-
redis其他常用命令汇总
-
keys命令组
命令 | 行为 | 返回值 | 使用示例(略去回调函数) |
---|---|---|---|
del | 删除一个(或多个)keys 被删除的keys的数量 | del(‘key1’[, ‘key2’, …]) | |
exists | 查询一个key是否存在 | 1/0 | exists(‘key’) |
expire | 设置一个key的过期的秒数 | 1/0 | expire(‘key’, seconds) |
pexpire | 设置一个key的过期的毫秒数 | 1/0 | pexpire(‘key’, milliseconds) |
expireat | 设置一个UNIX时间戳的过期时间 | 1/0 | expireat(‘key’, timestamp) |
pexpireat | 设置一个UNIX时间戳的过期时间(毫秒) | 1/0 | pexpireat(‘key’, milliseconds-timestamp) |
persist | 移除key的过期时间 | 1/0 | persist(‘key’) |
sort | 对队列、集合、有序集合排序 排序完成的队列等 | sort(‘key’[, pattern, limit offset count]) | |
flushdb | 清空当前数据库 |
总结几种类型特点:
1、string类型
字符串类型是redis中最为基础的数据存储类型,它在redis中是二进制安全的,value最多可以容纳的数据长度是512M,不关心具体格式,你可以用它存储 json 格式或 JPEG 图片格式的字符串。
应用场景:
- (1) 存储 MySQL 中某个字段的值
把 key 设计为 表名:主键名:主键值:字段名 - (2) 存储对象
string 类型支持任何格式的字符串,应用最多的就是存储 json 或其他对象格式化的字符串。(这种场景下推荐使用 hash 数据类型) - (3)常规key-value缓存应用;
- (4)常规计数:微博数,粉丝数等。
2、hash类型
hash用于存储对象,对象结构为 属性、值,值类型为string ;hash 类型很像一个关系型数据库的数据表,hash 的 Key 是一个唯一值,Value 部分是一个 hashmap 的结构。
应用场景:
-
存储部分变更的数据,如用户信息等
-
存放结构化数据,比如用户信息。在Memcached或CKV中,对于用户信息比如用户的昵称、年龄、性别、积分等,我们需要先序列化后存储为一个字符串的值,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。如下图:
-
Key是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。
不过这里需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而对其它客户端的请求完全不响应,这点需要格外注意。
-
可用来建索引。比如User对象,除了id有时还要按name来查询,可以建一个Key为user:name:id的Hash,在插入User对象时(set user:101{“id”:101,“name”:“calvin”}), 顺便往这个hash插入一条(hset user:name:id calvin 101),这时calvin作为hash里的一个key,值为101。按name查询的时候,用hgetuser:name:id calvin 就能从名为calvin的key里取出id。假如需要使用多种索引来查找某条数据时可以使用,一个hash key搞定,避免使用多个string key存放索引值。
-
HINCRBY同样可用于实现idmaker。相对string类型的idmaker每一个类型需要一个key,hash类型的用一个key即可。
3、list类型
list就是链表,略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。List的另一个应用就是消息队列,可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。
Redis的list是每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部添加或者删除元素,这样List即可以作为栈,也可以作为队列
应用场景:
-
消息队列系统
使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。
比如:将Redis用作日志收集器
实际上还是一个队列,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘。 -
比如sina微博:
在Redis中我们的最新微博ID使用了常驻缓存,这是一直更新的。但是做了限制不能超过5000个ID,因此获取ID的函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。
系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了 -
各种列表,比如twitter的关注列表、粉丝列表等,最新消息排行、每篇文章的评论等也可以用Redis的list结构来实现。
-
消息队列,可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出执行。这里的消息队列并没有ack机制,如果消费者把任务给Pop走了又没处理完就死机了怎么办?解决方法之一是加多一个sorted set,分发的时候同时发到list与sorted set,以分发时间为score,用户把任务做完了之后要用ZREM消掉sorted set里的job,并且定时从sorted set中取出超时没有完成的任务,重新放回list。另一个做法是为每个worker多加一个的list,弹出任务时改用RPopLPush,将job同时放到worker自己的list中,完成时用LREM消掉。如果集群管理(如zookeeper)发现worker已经挂掉,就将worker的list内容重新放回主list。
-
利用LRANGE可以很方便的实现list内容分页的功能。
-
取最新N个数据的操作:LPUSH用来插入一个内容ID,作为关键字存储在列表头部。LTRIM用来限制列表中的项目数最多为5000。如果用户需要的检索的数据量超越这个缓存容量,这时才需要把请求发送到数据库。
4、set类型:
无序集合,元素为string类型,元素唯一不重复,没有修改操作,set就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的set数据结构,可以存储一些集合性的数据。set中的元素是没有顺序的
应用场景:
-
在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。
-
某些需要去重的列表,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
-
可以存储一些集合性的数据,比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。又比如QQ有一个社交功能叫做“好友标签”,大家可以给你的好友贴标签,比如“大美女”、“土豪”、“欧巴”等等,这里也可以把每一个用户的标签都存储在一个集合之中。
-
想要知道某些特定的注册用户或IP地址,他们到底有多少访问了某个页面,可以这样实现:SADD page:day1:<page_id> <user_id> 。想知道特定用户的数量,使用SCARD page:day1:<page_id>。 需要测试某个特定用户是否访问了这个页面?SISMEMBER page:day1:<page_id>。
5、zset类型:
有序集合,元素为string类型,元素唯一不重复,没有修改操作,按score来排序
应用场景:
-
存放一个有序的并且不重复的集合列表,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
-
可以做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
-
排行榜相关:ZADD leaderboard 。 得到前100名高分用户很简单:ZREVRANGE leaderboard 0 99。用户的全球排名也相似,只需要执行:ZRANK leaderboard 。
-
新闻按照用户投票和时间排序,ZADD时的score = points / time^alpha, 这样用户的投票会相应的把新闻挖出来,但时间会按照一定的指数将新闻埋下去。
-
过期项目处理:使用unix时间作为关键字,用来保持列表能够按时间排序。对current_time和time_to_live进行检索,完成查找过期项目的艰巨任务。另一项后台任务使用ZRANGE…WITHSCORES进行查询,删除过期的条目