首先确定Redis服务是启动的
1 | [root@hadoop01 ~]# ps -fe | grep redis |
启动客户端,即可直接使用命令redis-cli
,默认就会直接启动6379的
1 | [root@hadoop01 ~]# redis-cli |
也可以连接6380的
1 | [root@hadoop01 ~]# redis-cli -p 6380 |
redis 默认是有16个库的,可以在连接的时候指定-n
,也可以连接成功之后切换。
注意:redis客户端中有help的使用,即连接成功后,输入help .按Tab键,就会看到redis中的命令是怎么用的,这里面他们会把命令做分组。
如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 127.0.0.1:6380> help @list
BLPOP key [key ...] timeout
summary: Remove and get the first element in a list, or block until one is available
since: 2.0.0
BRPOP key [key ...] timeout
summary: Remove and get the last element in a list, or block until one is available
since: 2.0.0
BRPOPLPUSH source destination timeout
summary: Pop an element from a list, push it to another list and return it; or block until one is available
since: 2.2.0
一、String
1、面向字符串一系列操作
先通过命令,我们看一下set
命令
1 | 127.0.0.1:6380> help set |
nx
:只有当设置的key不存在的时候,才去设置,使用场景: 分布式锁
xx
:只能更新,不存在的话,就不会处理
关于String的还哪些命令。还有mset
、append
、GETRANGE
1 | 127.0.0.1:6380> mset k1 v1 k2 v2 |
1 | 127.0.0.1:6380> append k1 hello |
1 | 127.0.0.1:6380> GETRANGE k1 2 6 |
上面的GETRANGE
也可以使用正反向索引
,反向索引,最后一个就是-1,倒数第二个就是-2,所以也可以这样实现
1 | 127.0.0.1:6380> GETRANGE k1 2 -1 |
SETRANGE
1 | 127.0.0.1:6380> setrange k1 2 steven |
strlen key
1 | 127.0.0.1:6380> strlen k1 |
2、type
及面向数值的操作
1 | 127.0.0.1:6380> type k1 |
1 | 127.0.0.1:6380> set k1 88 |
我们发现,即使我们设置一个int类型,他的type依然是String,但是如果这样看
1 | 127.0.0.1:6380> object encoding k1 |
注意,这int并不是类型,这个使用对象object指向value里面它的编码,是encoding的编码,为什么会有这种情况,因为在redis中,除了上面的字符串的操作,还有incr
、incrby
。这是面向数值的操作
1 | 127.0.0.1:6380> incr k1 |
1 | 127.0.0.1:6380> incrby k1 10 |
相应的也就有decr
、decrby
1 | 127.0.0.1:6380> decr k1 |
当然还有incrbyfloat
1 | 127.0.0.1:6380> incrbyfloat k1 0.5 |
关于encoding:
底层存储的时候就是按照字节存的,只是在key上做一个优化,key上如果没有做优化,每次计算,相当于都要先判断,这个能不能转成int的encoding。相当于做了一个加速的地方,可以让一些方法速度变快一些
3、redis的String是二进制安全的
什么是二进制安全?就是redis在与外界交互的时候,是严格通过字节流 交互的,因此,只要客户端有统一的编码,数据就不会被破坏,所以称为二进制安全
所以,当存一个字符大
的时候,如果编码是UTF-8
,那么length就是三个字节,如果是GBK
编码的话,就是两个字节
1 | 127.0.0.1:6380> set k2 大 |
Redis只会识别ASCII码的,超出ASCII的,就会直接按照16进制显示
退出客户端,按照以下方式进入客户端
1 | 127.0.0.1:6380> exit |
因此,在使用Redis,一定要在客户端沟通好数据的编码和解码
4、getset
设置新值,返回旧值
这个命令很多人认为是没有用的,因为你可以先get
,再set
,那么就要考虑成本问题,两次相当于在通信的时候发送了两个包,两次I/O请求。
这个命令可以减少一次I/O的通信
5、原子性操作msetnx
1 | 127.0.0.1:6380> mset k1 a k2 b |
NX
不存在时再设置,有一个失败了,其他的都失败
二、bitmap
位图
1、setbit
第一个命令setbit
,这个命令也归属于String;一个字节有8个二进制位
1 | 127.0.0.1:6380> help setbit |
setbit
中的这个offset是二进制位的offset,不是字节的二进制位
1 | 127.0.0.1:6380> setbit k3 1 1 |
此时二进制表示为
1 | 01000000 00000000 |
他的长度为:
1 | 127.0.0.1:6380> STRLEN k3 |
在ASCII
01000000正好表示一个@
符
1 | 127.0.0.1:6380> setbit k3 7 1 |
咋不超过8个字节的时候,不需要开辟新的字节,所以length还是1,当setbit k3 9 1
时,就会开辟新的字节,即
1 | 01000001 10000000 |
为啥ASCII不是utf-8?
字符集 ascii,其他一般叫做扩展字符集
扩展: 其他字符集不在对ascii重编码
2、bitpos
1 | 127.0.0.1:6380> help bitpos |
BITPOS key bit [start] [end]
key 二进制数 字节开始的位置,字节结束的位置
注意:这里是字节的开始结束位置,不是二进制位
K3的二进制:
1 | 01000001 10000000 |
1 | 127.0.0.1:6380> bitpos k3 1 0 0 |
即寻找k3中从第0个字节的位置到第0个位置的所有二进制位中,二进制位为1的位置(二进制位的位置)
1 | 127.0.0.1:6380> bitpos k3 1 1 1 |
3、bitcount
1 | 127.0.0.1:6380> help bitcount |
1 | 127.0.0.1:6380> bitcount k3 0 1 |
[start end]表示字节的开始和结束位置,count统计1出现的次数
4、bitop
位的操作
1 | 127.0.0.1:6380> help bitop |
1 | 127.0.0.1:6380> setbit k4 1 1 |
如果想设置一个B
1 | 127.0.0.1:6380> setbit k5 1 1 |
1 | 127.0.0.1:6380> bitop and andkey k4 k5 |
K4
(0100 0010)、k5
(0100 0100) 做按位与运算。得到的即0100 0000
,即@
1 | 127.0.0.1:6380> bitop or orkey k4 k5 #按位或 |
5、位图bitmap
的使用
(1)、需求一(空间小)
需求:需求,任意时间点,统计某一段时间,用户的登录软件的天数?
分析: 建一张用户登录表,来记录用户的登录记录,,最少需要哪些字段,用户的Id(按照4个字节算)、日期(也按照4个字节算)。因此用户登录一次需要8个字节,比如某宝,每天有很多人登录,一年再登录个200天,那数据会非常大,查询的时候,给定一个时间段,需要便利所有数据,成本很高
如果用位图
一年365天,先按照400天计算,每一天代表一个二进制位,从左到右,第一个二进制位代表第一天,以此类推,那么占用的字节数就是400/8=50个字节,也就是说,最多50个字节就可以表示一个人一年的登录记录
用户为key,天数为位
1 | 127.0.0.1:6380> setbit Steven 1 1 # 第二天登录 |
1 | 127.0.0.1:6380> bitcount Steven -2 -1 # 这里start end是字节,不是二进制位,所以要除以8,[-2 -1]即最后的16天登录数 |
1 | 127.0.0.1:6380> STRLEN Steven |
最高是46个字节(每个用户一年),这还是最浪费的情况,所以非常的节省空间
如果有1000w用户,每个用户一年46bit,那么一年所有的用户的大小为46000 0000=460M
*(2)、需求二(速度快)
需求:你是京东的开发工程师,618做活动,用户登录就送礼物,库房需要备多少礼物?假设京东有2亿用户
需要考虑这里面有很多的僵尸用户冷热用户/忠诚用户。因此统计活跃用户就很重要了
如何统计活跃统计?(未来还要支持随机时间窗口,即随意给定一个时间窗口,都可以算出这个窗口中国的活跃用户的数量)
分析: 比如1号到3号,就要考虑1号、2号、3号分别多少人,每个人连续登录需要去重
将需求1中的位图旋转一下,key日期,每个用户都有一个Id,让这个ID映射到每一个二进制位上
日期为key,用户为位
1 | 127.0.0.1:6380> setbit 20210301 1 1 # 比如下标为1的二进制位代表张三 |
如果窗口时间内,只要登录过就算活跃用户,那么1号,2号总共2个活跃用户
1 | 127.0.0.1:6380> bitop or destkey 20210301 20210302 # 做或运算 |
所以活跃用户为2
(3)面向数值计算的场景
抢购、秒杀、详情页(实时购买数等) -可以规避并发下对数据库的事务操作,完全由redis内存操作代替
另外,还有点赞、评论数、好友数都可以由redis内存操作
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !