前言
听说过二八定律的应该知道,我们百分之二十的东西是支撑着百分之八十的运作的。所以我们了解和学习一个东西一开始不需要事无巨细的每个都精通,可以优先了解 20%常用的,然后再去根据具体的需要了解剩下的 80%。毕竟时间有限,那么多业务要写。
常用的 Redis 命令
命令 | 描述 |
---|---|
keys * |
返回满足的所有键,可以模糊匹配,比如 keys abc* 代表 abc 开头的 key |
type key |
查看 key 对应的数据类型 |
exists key |
是否存在指定的 key,存在返回 1,不存在返回 0 |
expire key second |
设置某个 key 的过期时间 时间为秒 |
del key |
删除某个 key |
ttl key |
查看剩余时间,当 key 不存在时返回-2;存在但没有设置剩余生存时间时返回-1,返回 key 的剩余生存时间 |
persist key |
取消过期时间 |
pexpire key ms |
修改 key 的过期时间为毫秒 |
select |
选择数据库 0-15,默认为 16 个数据库 |
move key dbindex |
将当前数据中的 key 转移到其他数据库 |
randomkey |
随机返回一个 key |
rename key key1 |
重命名 key |
echo |
打印命令 |
dbsize |
查看数据库 key 数量 |
info |
查看数据库信息 |
config get * |
实时传储收到的请求,返回相关的配置 |
flushdb |
清空当前数据库 |
flushall |
清空所有数据库 |
expire 使用场景
- 限时的优惠活动信息
- 网站数据缓存(对于一些需要定时更新的数据,例如积分排行榜)
- 手机验证码
- 限制网站访客访问频率(例如:一秒钟最多 10 次)
key的命名建议
redis单个key允许存入512M大小
- key不要太长,尽量不要超过1024字节,消耗内存会降低查找的效率
- key也不要太短,太短的话,key的可读性降低
- 在一个项目中,key最好使用同一的命名规范,例如:
user:id:name
- key名称不区分大小写
Redis数据类型
String类型
string类型是Redis最基本的数据类型,一个键最大能存储512mb
string数据结构是简单的key-value类型,value其不仅是string,也可以是数字,是包含很多类型的特殊类型。
string类型是二进制安全的。意思是redis的string可以包含任何数据。比如序列化的对象进行存储,比如一张图片进行二进制存储,比如一个简单的字符串,数值等等。
String命令
赋值语法:
1 | Redis SET命令用于设置给定 key 的值,如果key已经存储值,set会复写旧值,且无视类型 |
2 | SET KEY_NAME VALUE |
3 | |
4 | 如果key不存在,则设值并返回1;如果key存在,则不设值并返回0 |
5 | 解决分布式锁 方案一,只有在key不存在时设置 key 的值,setnx(set if not exists)命令 |
6 | 指定的key不存在时,才会为key设置指定的值 |
7 | SETNX key value |
8 | |
9 | expired 设置key的值为1x,过期时间为10秒,十秒后键值被清理 |
10 | SETNX key 10 1x |
11 | |
12 | 给指定的 key 对应的值追加 value 至末尾,如果不存在,为其赋值 |
13 | APPEND key_name value |
取值语法:
1 | # Redis GET命令用于获取指定 key 的值 |
2 | # 如果key不存在,返回nil |
3 | # 如果key储存的值不是字符串类型,返回一个错误 |
4 | GET key_name |
5 | |
6 | # 用于获取存储在指定 key 中字符串的子字符串,字符串的截取范围由 start 和 end 两个偏移量决定 |
7 | GETRANGE key start end |
8 | |
9 | # 对key所储存的字符串值,获取指定偏移量上的位(bit) |
10 | GETBIT key offset |
11 | |
12 | # Getset 命令用于设置指定 key 的值,并返回 key 的旧值,当key不存在时,返回nil |
13 | # 先取值后赋值操作(先取出旧的值,再修改新的值),当key不存在返回nil |
14 | GETSET key_name value |
15 | |
16 | # 返回 key 所存储字符串的长度 |
17 | STRLEN key |
批量语法:
1 | # 批量写,一次性写入多个值 |
2 | MSET key1 value1 key2 value2... |
3 | |
4 | # 批量读,一次性读取多个值 |
5 | MGET key1 key2 key3... |
删值语法:
1 | # 删除指定的key,如果存在,返回值数字类型。 |
2 | DEL key_name |
自增/自减(value必须是数字类型哟,否则报错):
1 | # INCR 命令将 key 中存储的数字值增1。如果key不存在,那么key的值会先初始化位0, |
2 | # 然后再执行 INCR 操作 |
3 | INCR key_name |
4 | |
5 | # 给指定的 key 加上指定大小的增量 |
6 | INCRBY key_name 增量值 |
7 | |
8 | # DECR 命令将 key 中存储的数字值减1。如果key不存在,那么key的值会先初始化位0, |
9 | # 然后再执行 DECR 操作 |
10 | DECR key_name |
11 | |
12 | # 给指定的 key 减去指定大小的减值 |
13 | DECRBY key_name |
应用场景
- string通常用于保存单个字符串或JSON字符串数据
- string是二进制安全的,可以把一个图片文件作为字符串储存
- 计数器(常规key-value缓存应用,常规技术:粉丝数,文章浏览量)
Hash类型
Hash类型是String类型的field和value的映射表,或者说是string的集合。Hash特别适合存储对象,相比较而言,将一个对象类型存储在Hash类型要存储在String类型里占用更少的内存空间,并对整个对象存取。
可以看成具有key和value的map容器,该类型非常适合存储键值对象的信息。
如:uname,upass,age等。该类型的数据仅占用很少的磁盘空间(相比于json)
Redis中每个Hash可以存储2^32 - 1
键值对(40多亿)
常用命令
1 | 赋值语句: |
2 | 指定的key,设定 field value |
3 | HSET key field value |
4 | |
5 | 同时将多个field-value(域-值)对设置到哈希表 key 中 |
6 | HMSET key field value [field1 value1]... |
7 | |
8 | |
9 | 取值语句: |
10 | 获取存储在Hash中的值,根据field 获取 value |
11 | HGET key field |
12 | |
13 | 获取 key 所有给定字段的 value |
14 | HMGET key field [field1] |
15 | |
16 | 返回Hash表中所有的字段和值 |
17 | HGETALL key |
18 | |
19 | 获取所有哈希表中的字段 |
20 | HKEYS key |
21 | |
22 | 获取哈希表中字段的数量 |
23 | HLEN key |
24 | |
25 | |
26 | 删除语法: |
27 | 删除一个或多个hash表字段 |
28 | HDEL key field [field2] |
29 | |
30 | |
31 | 其它语法: |
32 | 只有在字段 field 不存在时,设置哈希表字段的值 |
33 | HSETNX key field value |
34 | |
35 | 为哈希表 key 中的指定字段的整数值加上增量 increment |
36 | HINCRBY key field increment |
37 | |
38 | 为哈希表 key 中的指定字段的浮点数值加上增量 increment |
39 | HINCRBYFLOAT key field increment |
40 | |
41 | 查看哈希表 key 中,指定的字段是否存在 |
42 | HEXISTS key field |
应用场景
Hash的应用场景:(存储一个用户信息对象数据)
- 常用于存储一个对象
Hash时最接近数据库结构的数据类型,可以将数据库一条记录或程序中一个对象转换成hashmap存放在redis中。
用户ID为查找的key,存储的value用户对象包含姓名、年龄、生日等信息,如果用普通的key/value结构来存储,主要以下两种存储方式:
- 将用户id作为查找key,把其他信息封装成一个对象以序列的方式存储,这种方式缺点是,增加了序列化/反序列化的开销,并且需要修改其中一项信息时,需要把整个对象取回,并修改操作需要对并发进行保护,引入CAS等复杂问题
- 这个用户信息对象由多少成员就存储多少个key-value对,用户id+对应的名称作为唯一标识来取得对应属性的值,虽然省去序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。
List 类型
List类型是一个链表结构的集合,其主要功能有push、pop、获取元素等。更详细的说,List类型是一个双端链表的节后,我们可以通过相关操作进行集合的头部或者尾部添加和删除元素,List的设计非常简单精巧,及可以作为栈,也可以作为队列,满足绝大多数的需求。
按照插入顺序排序,你可以添加一个元素到列表头部或者尾部,一个列表最多可以包含 2^32-1 个元素(40忆个元素)类似Java中的LinkedList
常用命令
赋值语法:
1 | 将一个或多个值插入到列表头部(从左侧添加) |
2 | LPUSH key value1 [value2] |
3 | |
4 | 在列表中添加一个或多个值(从右侧添加) |
5 | RPUSH key value1 [value2] |
6 | |
7 | 将一个值插入到已存在的列表头部。如果列表不存在,操作无效 |
8 | LPUSHX key value |
9 | |
10 | 一个值插入已存在的列表尾部(最右边)。如果列表不在,操作无效 |
11 | RPUSHX key value |
取值操作:
1 | 获取列表长度 |
2 | LLEN key |
3 | |
4 | 通过索引获取列表中的元素 |
5 | LINDEX key index |
6 | |
7 | 获取列表指定范围的元素 |
8 | LRANGE key start end |
描述:返回列表中指定区间内的元素,区间以偏移量start和end指定。
其中0表示列表第一个元素,1表示第二个元素,以此类推
也可以负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推
删除操作:
1 | 移出并获取列表的第一个元素(从左侧删除) |
2 | LPOP key |
3 | |
4 | 移出列表的最后一个元素,返回值为移除的元素(从右侧删除) |
5 | RPOP key |
6 | |
7 | 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 |
8 | BLPOP key1 [key2] timeout |
9 | |
10 | 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 |
11 | BRPOP key1 [key2] timeout |
12 | |
13 | 对一个列表进行裁剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除 |
14 | LTRIM key start stop |
修改操作:
1 | 通过索引设置列表元素的值 |
2 | LSET key index value |
3 | |
4 | 在列表的元素前或者后插入元素 |
5 | 将值 value 插入到列表 key 当中,位于值 world 之前或之后 |
6 | LINSERT key BEFORE|AFTER world value |
高级命令
高级语法:
1 | 移除列表的最后一个元素,并将该元素添加到另一个列表并返回 |
2 | RPOPLPUSH source destination |
3 | |
4 | 示例描述: |
5 | a1的最后元素移到a2的左侧 |
6 | RPOPLPUSH a1 a2 |
7 | |
8 | 循环列表,将最后元素移到最左侧 |
9 | RPOPLPUSH a1 a1 |
10 | |
11 | 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它;如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 |
12 | BRPOPLPUSH source destination timeout |
应用场景
项目常用:
对数据大的集合数据删减
列表数据显示、关注列表、粉丝列表、留言评论、分页、热点新闻(top5)等
利用LRANGE还可以很方便的实现分页的功能,在博客系统中,每篇博文的评论也可以存入一个单独的list中
任务队列
List通常用来实现一个消息队列,而且可以确保先后顺序,不必像MySQL那样还要通过ORDER BY进行排序
任务队列介绍(生产者和消费者模式):
在处理web客户端发送的命令请求,某些操作的执行时间会比我们预期的更长一些,通过将等待执行任务的相关信息放入队列里面,并在之后对队列进行处理,用户可以推迟执行那些需要一段时间才能完成的操作,这种将工作交给任务处理器来执行的做法被称为任务队列(Task Queue)
Set类型
Redis的Set是String类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复数据。Redis中集合是通过哈希表实现的,set是通过hashtable实现的。
集合中最大的成员数为 2^32 - 1
(40多亿个成员),类似于Java中的HashTable集合
常用命令
赋值语法:
1 | 向集合添加一个或多个成员 |
2 | SADD key member1 [member2] |
取值语法:
1 | 获取集合的成员数 |
2 | SCARD key |
3 | |
4 | 返回集合中的所有成员 |
5 | SMEMBERS key |
6 | |
7 | 判断 member 元素是否是集合 key 的成员 |
8 | SISMEMBER key member |
9 | |
10 | 返回集合中一个或多个随机数 |
11 | SRANDMEMBER key [count] |
删除语法:
1 | 移除集合中一个或多个成员 |
2 | SREM key member1 [member2] |
3 | |
4 | 移除并返回集合中的一个随机元素 |
5 | SPOP key [count] |
6 | |
7 | 将 member 元素从 source 集合移动到 destination 集合 |
8 | SMOVE source destination member |
差集语法:
1 | 返回给点所有集合的差值(左侧) |
2 | SDIFF key1 key2 |
3 | |
4 | 返回给定所有集合的差集并存储在 destination 中 |
5 | SDIFFSTORE destination key1 [key2] |
交集语法:
1 | 返回给定所有集合的交集(所有元素) |
2 | SINTER key1 [key2] |
3 | |
4 | 返回给定所有集合的交集并存储在 destination 中 |
5 | SINTERSTORE destination key1 [key2] |
并集语法:
1 | 返回所有给定集合的并集 |
2 | SUNION key1 [key2] |
3 | |
4 | 所有给定集合的并集存储在 destination 中 |
5 | SUNIONSTORE destination key1 [key2] |
应用场景
常应用于:对两个集合间的数据计算进行交集、并集、差集计算
- 利用集合操作,可以取不同兴趣圈子的交集,以非常方便的实现如共同关注,共同喜好,二度好友等功能。对上面的所有集合操作,你还可以使用不同的命令选择结果返回给客户端还是存储到一个新的集合中。
- 利用唯一性,可以统计访问网站的所有独立ip、存取当天[某天]的活跃用户列表
ZSet类型
有序集合(sorted set)
- Redis有序集合和集合一样也是string类型元素的集合,且不允许重复的成员
- 不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序
- 有序集合的成员是唯一的,但(score)却可以重复
- 集合是通过哈希实现的。集合最大的成员数为
2^32 - 1
(每个集合可存放40亿个成员)。
常用命令
赋值语法:
1 | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
2 | ZADD key score1 member1 [score2 member2] |
取值语法:
1 | 获取有序集合的成员数 |
2 | ZCARD key |
3 | |
4 | 计算在有序集合中指定区间分数的成员 |
5 | ZCOUNT key min max |
6 | |
7 | 返回有序集合中指定成员的索引 |
8 | ZRANGE key member |
9 | |
10 | 通过索引区间返回有序集合指定区间内的成员(低到高) |
11 | ZRANGE key start stop [WITHSCORES] |
12 | |
13 | 通过分数返回有序集合指定区间内的成员 |
14 | ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] |
15 | |
16 | 返回有序集合中指定区间内的成员,通过索引、分数从高到低 |
17 | ZREVRANGE key start stop [WITHSCORES] |
18 | |
19 | 返回有序集合中指定分数分区区间内的成员,分数从高到低排序 |
20 | ZREVRANGESCORE key max min [WITHSCORES] |
删除语法:
1 | 删除集合 |
2 | DEL key |
3 | |
4 | 移除有序集合中的一个或多个成员 |
5 | ZREM key member [member1 ...] |
6 | |
7 | 移除有序集合中给定的排名区间的所有成员(第一名是0)(低到高排序) |
8 | ZREMRANGEBYRANK key start stop |
9 | |
10 | 移除有序集合中给定的分数区间的所有成员 |
11 | ZREMRANGEBYSCORE key min max |
12 | |
13 | 增加 member 元素的分数 increment,返回值是更改后的分数 |
14 | ZINCRBY key increment member |
应用场景
销售排行,积分排行
- Twitter 的 public timeline 可以以发表时间作为 score 来储存,这样获取时就是自动按时间排好序的
- 一个存储全班同学成绩的 sorted set,其集合 value 可以是同学的学号,而 score 就可以是其考的分数,这样在数据插入集合的时候,就已经进行了天然的排序。
- 用sorted set来做带权重的队列,普通消息的score 为1,重要消息的score为2,然后工作线程可以选择score的倒序来获取工作任务。让重要的任务优先执行。
Hyperloglog类型
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
常用命令
赋值语法:
1 | 添加指定元素到 HyperLogLog 中 |
2 | PFADD key element [element ...] |
3 | |
4 | 将多个 HyperLogLog 合并为一个 HyperLogLog |
5 | PFMERGE destkey sourcekey [sourcekey ...] |
取值语法:
1 | 返回给定 HyperLogLog 的基数估算值。 |
2 | PFCOUNT key [key ...] |
应用场景
基数不大,数据量不大就用不上,会有点大材小用浪费空间
有局限性,就只是统计基数数量,而没办法去知道具体的内容是什么
- 统计注册IP数
- 统计每日访问IP数
- 统计页面实时UV数
- 统计在线用户数
- 统计用户每天搜索不同词条的个数
- 统计真实文章阅读数
总结
掌握这些基本的redis操作已经是不在话下,当然具体怎么用用哪个类型还是要大家多多动手实践。