笔记整理自【尚硅谷】Redis 6 入门到精通 超详细 教程
keys *
:查看当前库所有 keyexists key
:判断某个 key 是否存在type key
:查看你的 key 是什么类型del key
:删除指定的 key 数据unlink key
:根据 value 选择非阻塞删除,仅将 keys 从 keyspace 元数据中删除,真正的删除会在后续异步操作expire key 10
:为给定的 key 设置过期时间ttl key
:查看还有多少秒过期,−1-1−1 表示永不过期,−2-2−2 表示已过期select
:命令切换数据库dbsize
:查看当前数据库的 key 的数量flushdb
:清空当前库flushall
:通杀全部库简介
常用命令
set
:添加键值对
get
:查询对应键值
append
:将给定的
strlen
:获得值的长度
setnx
:只有在 key 不存在时,设置 key 的值
incr
:将 key 中储存的数字值增 111,只能对数字值操作,如果 key 为空,新增 value 值为 111(具有原子性)
decr
:将 key 中储存的数字值减 111,只能对数字值操作,如果 key 为空,新增 value 值为 −1-1−1(具有原子性)
incrby/decrby
:将 key 中储存的数字值增减。自定义步长
原子性
所谓 原子 操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
在单线程中, 能够在单条指令中完成的操作都可以认为是"原子操作",因为中断只能发生于指令之间。
在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。
Redis单命令的原子性主要得益于Redis的单线程。
mset
:同时设置一个或多个 key-value 对
mget
:同时获取一个或多个 value
msetnx
:同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
getrange
:获得值的范围(类似 java 中的 substring,前包,后包)
setrange
:用 <起始位置>
开始(索引从 000 开始)
setex
:设置键值的同时,设置过期时间,单位秒
getset
:以新换旧,设置了新值同时获得旧值
数据结构
capacity
一般要高于实际字符串长度len
。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是字符串最大长度为 512M。简介
常用命令
lpush/rpush
: 从左边/右边插入一个或多个值。
lpush k1 v1 v2 v3
lrange k1 0 -1
输出:v3 v2 v1rpush k1 v1 v2 v3
rrange k1 0 -1
输出:v1 v2 v3
lpop/rpop
:从左边/右边吐出一个值。值在键在,值光键亡。
rpoplpush
:从
lrange
:按照索引下标获得元素(从左到右)
lrange mylist 0 -1
:000:左边第一个,−1-1−1:右边第一个,(0−10\ -10 −1 表示获取所有)lindex
:按照索引下标获得元素(从左到右)
llen
:获得列表长度
linsert
:在
lrem
:从左边删除 n 个 value(从左到右)
lset
:将列表 key 下标为 index 的值替换成 value
数据结构
简介
常用命令
sadd .....
:将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略smembers
:取出该集合的所有值。sismember
:判断集合 scard
:返回该集合的元素个数。srem ....
:删除集合中的某个元素spop
:随机从该集合中吐出一个值srandmember
:随机从该集合中取出 n 个值,不会从集合中删除smove value
:把集合中一个值从一个集合移动到另一个集合sinter
:返回两个集合的交集元素sunion
:返回两个集合的并集元素sdiff
:返回两个集合的差集元素(key1 中的,不包含 key2 中的)数据结构
简介
常用命令
hset
:给 hget
:从 hmset ...
: 批量设置 hash 的值hexists
:查看哈希表 key 中,给定域 field 是否存在hkeys
:列出该 hash 集合的所有 fieldhvals
:列出该 hash 集合的所有 valuehincrby
:为哈希表 key 中的域 field 的值加上增量 111 −1-1−1hsetnx
:将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在数据类型
简介
常用命令
zadd …
:将一个或多个 member 元素及其 score 值加入到有序集 key 当中zrange [WITHSCORES]
:返回有序集 key 中,下标在 zrangebyscore key min max [withscores] [limit offset count]
:返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。zrevrangebyscore key max min [withscores] [limit offset count]
:同上,改为从大到小排列zincrby
:为元素的 score 加上增量zrem
:删除该集合下,指定值的元素zcount
:统计该集合,分数区间内的元素个数zrank
:返回该值在集合中的排名,从 0 开始。案例
如何利用 zset 实现一个文章访问量的排行榜?
数据结构
简介
实例
对比有序链表和跳跃表,从链表中查询出 515151
有序链表
要查找值为 515151 的元素,需要从第一个元素开始依次查找、比较才能找到。共需要 666 次比较。
跳跃表
从第 222 层开始,111 节点比 515151 节点小,向后比较。
212121 节点比 515151 节点小,继续向后比较,后面就是 NULL 了,所以从 212121 节点向下到第 111 层
在第 111 层,414141 节点比 515151 节点小,继续向后,616161 节点比 515151 节点大,所以从 414141 向下
在第 000 层,515151 节点为要查找的节点,节点被找到,共查找 444 次。
跳跃表在某些情况下比有序链表效率要高。
简介
现代计算机用二进制(位) 作为信息的基础单位, 1个字节等于8位, 例如“abc”字符串是由3个字节组成, 但实际在计算机存储时将其用二进制表示, “abc”分别对应的ASCII码分别是97、 98、 99, 对应的二进制分别是01100001、 01100010和01100011,如下图:
合理地使用操作位能够有效地提高内存使用率和开发效率。
Redis 提供了 Bitmaps 这个“数据类型”可以实现对位的操作:
常用命令
setbit
:设置 Bitmaps 中某个偏移量的值(000 或 111)
offset:偏移量从 000 开始
实例
每个独立用户是否访问过网站存放在 Bitmaps 中, 将访问的用户记做 111, 没有访问的用户记做 000, 用偏移量作为用户的 id。
设置键的第 offset 个位的值(从 000 算起),假设现在有 202020 个用户,userid=1,6,11,15,19userid=1,6,11,15,19userid=1,6,11,15,19 的用户对网站进行了访问, 那么当前 Bitmaps 初始化结果如图:
unique:users:20201106
代表 2020-11-06 这天的独立访问用户的 Bitmaps
getbit
:获取 Bitmaps 中某个偏移量的值
获取键的第 offset 位的值(从 000 开始算)
实例
获取 id=8id=8id=8 的用户是否在 2020-11-06 这天访问过, 返回 000 说明没有访问过:
注:因为 100100100 根本不存在,所以也是返回 000。
bitcount
:统计字符串从 start 字节到 end 字节比特值为 111 的数量
统计字符串被设置为 111 的 bit 数。一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。start 和 end 参数的设置,都可以使用负数值:比如 −1-1−1 表示最后一个位,而 −2-2−2 表示倒数第二个位,start、end 是指 bit 组的字节的下标数,二者皆包含。
注意:redis 的 setbit 设置或清除的是 bit 位置,而 bitcount 计算的是 byte 位置。
举例
K1 [01000001 01000000 00000000 00100001],对应 [0,1,2,3]
bitcount K1 1 2 : 统计下标1、2字节组中bit=1的个数,即 01000000 00000000
=> bitcount K1 1 2 => 1bitcount K1 1 3 : 统计下标1、2、3字节组中bit=1的个数,即 01000000 00000000 00100001
=> bitcount K1 1 3 => 3bitcount K1 0 -2 : 统计下标0到下标倒数第2,字节组中bit=1的个数,即 01000001 01000000 00000000
=> bitcount K1 0 -2 => 3
bitop and(or/not/xor)
:bitop 是一个复合操作, 它可以做多个 Bitmaps 的 and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在 destkey 中。
实例
2020-11-04 日访问网站的 userid=1,2,5,9userid=1,2,5,9userid=1,2,5,9
setbit unique:users:20201104 1 1
setbit unique:users:20201104 2 1
setbit unique:users:20201104 5 1
setbit unique:users:20201104 9 1
2020-11-03 日访问网站的 userid=0,1,4,9userid=0,1,4,9userid=0,1,4,9
setbit unique:users:20201103 0 1
setbit unique:users:20201103 1 1
setbit unique:users:20201103 4 1
setbit unique:users:20201103 9 1
计算出两天都访问过网站的用户数量:
bitop and unique:users:and:20201104_03 unique:users:20201103 unique:users:20201104
计算出任意一天都访问过网站的用户数量(例如月活跃就是类似这种),可以使用 or 求并集:
Bitmaps 与 set 对比
假设网站有1亿用户, 每天独立访问的用户有5千万, 如果每天用 集合 类型和 Bitmaps 分别存储活跃用户可以得到表
很明显, 这种情况下使用 Bitmaps 能节省很多的内存空间, 尤其是随着时间推移节省的内存还是非常可观的。
但 Bitmaps 并不是万金油, 假如该网站每天的独立访问用户很少, 例如只有10万(大量的僵尸用户),那么两者的对比如下表所示, 很显然, 这时候使用 Bitmaps 就不太合适了, 因为基本上大部分位都是 000。
简介
在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站 PV(PageView,页面访问量),可以使用 Redis 的 incr、incrby 轻松实现。
但像 UV(UniqueVisitor,独立访客)、独立 IP 数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。
解决基数问题有很多种方案:
以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。
能否能够降低一定的精度来平衡存储空间?Redis 推出了 HyperLogLog。
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12KB 内存,就可以计算接近 2642^{64}264 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
什么是基数?
常用命令
pfadd
:添加指定元素到 HyperLogLog 中
将元素添加到指定HyperLogLog数据结构中。如果执行命令后 HLL 估计的近似基数发生变化,则返回 111,否则返回 000。
pfcount
:计算 HLL 的近似基数,可以计算多个 HLL,比如用 HLL 存储每天的 UV,计算一周的 UV 可以使用 777 天的 UV 合并计算即可
pfmerge
:将一个或多个 HLL 合并后的结果存储在另一个 HLL 中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得
简介
Redis 3.2 中增加了对 GEO 类型的支持。GEO,Geographic,地理信息的缩写。该类型,就是元素的二维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。
常用命令
geoadd
:添加地理位置(经度,纬度,名称)
实例
geoadd china:city 121.47 31.23 shanghai
geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing
两极无法直接添加,一般会下载城市数据,直接通过 Java 程序一次性导入。
有效的经度从 −180-180−180 度到 180180180 度。有效的纬度从 −85.05112878-85.05112878−85.05112878 度到 85.0511287885.0511287885.05112878 度。
当坐标位置超出指定范围时,该命令将会返回一个错误。
已经添加的数据,是无法再次往里面添加的。
geopos
:获得指定地区的坐标值
geodist
:获取两个位置之间的直线距离
实例
获取两个位置之间的直线距离
单位
m 表示单位为米[默认值]。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位
georadius
:以给定的经纬度为中心,找出某一半径内的元素
实例