基本命令
基本命令
172.17.0.2:6379> SELECT 0 选择单机数据库,conf文件有配置数据库个数
OK
172.17.0.2:6379> EXISTS lsit 查看key是否存在
(integer) 0
172.17.0.2:6379> FLUSHDB 清除所在DB
OK
172.17.0.2:6379> FLUSHALL 清除所有DB
OK
REDIS类型
STRING 字符串
内部实现
String 类型的底层的数据结构实现主要是 int 和 SDS(简单动态字符串)。
特性
- 可以保存二进制数据
- 获取字符串长度为O(1),SDS数据结构存有len字段
- 保存修改时会判断字符串长度,自动扩容,防止缓冲区溢出
常用语法
# 字符串 || 数字
set a 123
get a
mset a 123 b 456
mget a b
# 过期
expire a 60
ttl a
# 数字递增递减
incr a [num]
decr a [num]
# 不存在插入 no exists
setnx key value
使用场景
- 缓存对象(json)
- 常规计数(incr)
- 分布式锁(setnx)
- 分布式系统中session记录
hash
内部实现
使用压缩列表或哈希表
- 当元素个数小于512个且元素最大长度不大于64字节,则使用压缩列表(实际上是一个数组,所以长度有限)
- 不满足以上条件,则使用哈希表
redis7.0之后使用listpack结构
常用语法
# 单条设置获取
hset name key value
hget name key
# 批量设置获取
hmset name key value key1 value1
hmget name key key1
# 删除
hdel name key key1
# hash表key数量
hlen name
# hash表所有key
hgetall name
# 增量
hincrby name key num
使用场景
- 缓存对象
LIST 链表
内部实现
list底层实现是 双向列表 或 压缩列表(ziplist) 。redis3.2版本后使用quicklist实现
- 当元素个数小于512个且元素最大长度不大于64字节,则使用压缩列表(实际上是一个数组,所以长度有限)
- 不满足以上条件则使用双向列表
常用语法
- 插入
(integer) 1
172.17.0.2:6379> LPUSH list two 左插入一条数据
(integer) 2
172.17.0.2:6379> RPUSH list pre-one 右插入一条数据
(integer) 3
172.17.0.2:6379> RPUSH list pre-one 右插入一条数据
(integer) 3
172.17.0.2:6379> LSET list 2 11 修改list中index == 2的值, 发现index下标没有,不会插入,只能修改。一般是不会用这个指令的
(error) ERR index out of range
172.17.0.2:6379> LSET list 1 11
OK
172.17.0.2:6379> LINSERT list BEFORE 3 before 在3前插入一个数据,把BEFORE 改成 AFTER就是后插
(integer) 5
- list长度
172.17.0.2:6379> LLEN list
(integer) 1
- 删除元素
172.17.0.2:6379> LPOP list 左取出一条黑色数据
"two"
172.17.0.2:6379> RPOP list 右取出一条数据
"pre-one"
172.17.0.2:6379> LTRIM list 2 4 数据修剪,只留下2 4的数据,其他进行删除
OK
- 查找
172.17.0.2:6379> LRANGE list 0 -1 范围查找
1) "two"
2) "one"
3) "pre-one"
172.17.0.2:6379> LINDEX list 0
"two"
- 移动
172.17.0.2:6379> RPOPLPUSH list new_list 将list链表中的右边数据pop出来,左push到new_list列表中,因为是原子操作,所以比拆分跟靠谱
"4"
172.17.0.2:6379> LRANGE new_list 0 -1
1) "4"
# 阻塞等待listPOP,没有元素则阻塞释放CPU,timeout后结束
# 用于队列
BRPOP list timeout
BLPOP list timeout
使用场景
- 消息队列
- 消息可靠性:使用 BRPOPLPUSH插入另外一条队列,做消息被封
- 重复消费:使用全局ID唯一性,
- 顺序性:队列本身具有顺序性,只要队尾插入,队头获取。阻塞式读取BRPOP 释放CPU等待元素进入
SET 集合(不会重复元素)
Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。
一个集合最多可以存储 2^32-1
个元素。概念和数学中个的集合基本类似,可以交集,并集,差集等等,所以 Set 类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。
内部实现
由hash表或整数集合实现
- 元素小于512个且都是整数,使用整数集合实现
- 不满足以上条件,则使用hash表实现
常用语法
# 往集合key中存入元素,元素存在则忽略,若key不存在则新建
SADD key member [member ...]
# 从集合key中删除元素
SREM key member [member ...]
# 获取集合key中所有元素
SMEMBERS key
# 获取集合key中的元素个数
SCARD key
# 判断member元素是否存在于集合key中
SISMEMBER key member
# 从集合key中随机选出count个元素,元素不从key中删除
SRANDMEMBER key [count]
# 从集合key中随机选出count个元素,元素从key中删除
SPOP key [count]
# 交集运算
SINTER key [key ...]
# 将交集结果存入新集合destination中
SINTERSTORE destination key [key ...]
# 并集运算
SUNION key [key ...]
# 将并集结果存入新集合destination中
SUNIONSTORE destination key [key ...]
# 差集运算
SDIFF key [key ...]
# 将差集结果存入新集合destination中
SDIFFSTORE destination key [key ...]
使用功能
- 抽奖:插入集合中随机返回元素,并删除该元素 (SPOP)
- 共同好友/爱好:多个集合的交集 (SUNION)
- 某篇文章的点赞人和数(SADD)
中文文档: http://redis.cn/commands.html#set
zset有序集合
Zset 类型(有序集合类型)相比于 Set 类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序集合的元素值,一个是排序值。
内部实现
Zset 类型的底层数据结构是由压缩列表或跳表实现的:
- 如果有序集合的元素个数小于
128
个,并且每个元素的值小于64
字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构; - 不满足以上条件,则使用跳表结构
常用语法
# 往有序集合key中加入带分值元素
ZADD key score member [[score member]...]
# 往有序集合key中删除元素
ZREM key member [member...]
# 返回有序集合key中元素member的分值
ZSCORE key member
# 返回有序集合key中元素个数
ZCARD key
# 为有序集合key中元素member的分值加上increment
ZINCRBY key increment member
# 正序获取有序集合key从start下标到stop下标的元素
ZRANGE key start stop [WITHSCORES]
# 倒序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES]
# 返回有序集合中指定分数区间内的成员,分数由低到高排序。
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
# 返回指定成员区间内的成员,按字典正序排列, 分数必须相同。
ZRANGEBYLEX key min max [LIMIT offset count]
# 返回指定成员区间内的成员,按字典倒序排列, 分数必须相同
ZREVRANGEBYLEX key max min [LIMIT offset count]
使用场景
- 排行榜(ZINCRBY + ZREVRANGE)
- 延时队列(ZADD queue timestamp task_id + ZRANGEBYSCORE)
Geo
地图功能
GEOADD waimai lng lat location1 #集合名是waimai 添加location1这个点的信息
GEOADD waimai lng lat location2 #集合名是waimai 添加location2这个点的信息
GEOPOS waimai location1 #获得点信息
GEODIST waimai location1 location2 #计算两点距离
GEORADIUS waimai lng lat 5 km #在外卖这个集合内 给一个指定的经纬度为原点,5km为半径查找附近的点,后面还有参数可以返回每两个点的距离
GEORADIUSBYMEMBER location1 5 km #在外卖这个集合内 计算以location1为原点,5km为半径查找附近的点,后面还有参数可以返回每两个点的距离
使用场景
- 可以算出两点间距离
- 附近的人/附近的店铺(这样不用触发mysql function直接在内存中运算,快很多)
HyperlogLog
基数: 两个集合的并集(不重复元素),他跟集合的交集的区别
- 他无法查看集合内元素,只基数,所以内存占用小
127.0.0.1:6379> PFADD set1 1 2 3 4 5 5 6 6 #添加元素进集合
(integer) 1
127.0.0.1:6379> PFADD set2 5 6 7 8 8 9
(integer) 1
127.0.0.1:6379> PFCOUNT set2 #集合个数
(integer) 5
127.0.0.1:6379> PFCOUNT set1 set2 #集合个数想加
(integer) 9
127.0.0.1:6379> PFMERGE set3 set1 set2 #两个集合的并集
OK
127.0.0.1:6379> PFCOUNT set3
(integer) 9
使用场景
- 统计UV等统计内容,可以容错的统计
BitMaps
内部实现
8bit = 1byte = 0.001kb
bitmap通过bit 存放0,1来对应某个元素。
bimap一个key最多存512M,2^32bit存储位(40亿bit),已经很够用了
Bitmap 本身是用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型。
String 类型是会保存为二进制的字节数组,所以,Redis 就把字节数组的每个 bit 位利用起来,用来表示一个元素的二值状态,你可以把 Bitmap 看作是一个 bit 数组。
常用语法
# 设置位
setBit(key, offset, value)
# 获取位
getBit(key, offset)
# 统计1
bitCount(key)
# 二级制位运算
bitOp(operation, desKey, key)
使用场景
-
打卡功能 比如gayhub上的签到等等,使用 01标记的数据
start = 2021.01.01; end = time(); day = floor((end - start) / 86400); //第N天 key = user_id; setBit(user_id, day, value);
-
属性标记(例如1亿个用户,每个用户都有什么标签)
key = label_id . user_id; //为什么不是一个用户一个key,因为有1亿用户就有1亿个key了,而标签不会有1亿个标签 setBit(key, offest=user_id, value); #如果使用mysql可以用常量累加,虽然存确实已经压缩了,可是取需要每一行数据都做位与运算,所以不行 #如果使用mysql还可以使用一个label一个列,当要添加新的label时就需要改动表结构,所以也不行
-
用户在线状态
key = online or offline; setBit(key, user_id, value);
-
活跃用户
key = date_activity_user; setBit(key, user_id, value);