- redis是一个高性能的 key-value 数据库,是跨平台的非关系型数据库
- redis基于内存,并且支持持久化。可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- redis支持的数据类型丰富,包括key-value类型数据,字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)等
- redis的key值是二进制安全的,也就说可以用任何二进制序列作为key值,从简单字符串到一个图片文件都可以。
(1)key的取值不能太长,太长消耗内容,而且查找键值成本太高
(2)key值也不能太短,太短会导致看不懂键的含义 - Redis的所有操作都是原子性的,要么全部成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
更多概念可以看菜鸟教程的 redis 部分
目录
启动redis
方式一
进入redis安装目录的bin目录下面 nohup redis-server redis.conf &
按 ctrl + c 退出,然后再输入 redis-cli
方式二
打开两个终端,第一个终端进入bin目录下,输入 ./redis-server 启动服务端
第二个终端进入bin目录,输入 ./redis-cli 启动客户端,在客户端输入命令
启动完redis后,可以下载软件工具,使用可视化界面
String
新增,获取,更改
127.0.0.1:6379> set a abc //新增
OK
127.0.0.1:6379> get a //获取
"abc"
127.0.0.1:6379> set a xyz //更改,用新的值覆盖原先的值
OK
127.0.0.1:6379> get a
"xyz"
批量插入,批量获取
127.0.0.1:6379> mset b bb c cc //mset批量插入
OK
127.0.0.1:6379> mget b c //mget批量获取
1) "bb"
2) "cc"
设置过期时间
EX —— 秒
PX —— 毫秒
Redis中可以给Key设置一个生存时间(秒或毫秒),当达到这个时长后,这些键值将会被自动删除
(1)创建键值的时候设置过期时间
127.0.0.1:6379> set a a EX 5 //新增键值a a,并给这个键值设置5秒后过期
OK
127.0.0.1:6379> get a //5秒内获取
"a"
127.0.0.1:6379> get a //5秒后获取
(nil)
(2)给已经存在的key设置过期时间
格式:
EXPIRE key seconds
PEXPIRE key milliseconds
127.0.0.1:6379> expire b 5
(integer) 1
127.0.0.1:6379> get b //5s内获取
"bb"
127.0.0.1:6379> get b //5s后获取
(nil)
(3)设置在指定的时间戳 过期
EXPIREAT key timestamp
PEXPIREAT key milliseconds-timestamp
127.0.0.1:6379> expireat c 1636974900 //2021-11-15 19:15:00的时间戳
(integer) 1
127.0.0.1:6379> get c
"cc"
127.0.0.1:6379> get c
(nil)
(4)查看剩余时间
key存在但没有设置TTL,返回-1
key存在,但还在生存期内,返回剩余的秒或者毫秒
key曾经存在,但已经消亡,返回-2(2.8版本之前返回-1)
127.0.0.1:6379> expire k 5
(integer) 1
127.0.0.1:6379> ttl k //还剩3s过期
(integer) 3
127.0.0.1:6379> ttl k
(integer) -2
查找key
keys 后面加上一个正则表达式,即可找到指定的key
keys * 任意长度字符
keys ? 任意一个字符
keys [] 字符集合,表示可以是集合中的任意一个
127.0.0.1:6379> keys *
1) "c"
2) "bb"
3) "a"
127.0.0.1:6379> keys ?
1) "c"
2) "a"
127.0.0.1:6379> keys ??
1) "bb"
127.0.0.1:6379> keys b?
1) "bb"
127.0.0.1:6379> keys [ac]
1) "c"
2) "a"
key的类型,key是否存在,key重命名,key删除
redis中
运行结果正确返回 (integer) 1
运行结果错误返回 (integer) 0
127.0.0.1:6379> type a //判断类型
string
127.0.0.1:6379> exists a //判断是否存在
(integer) 1
127.0.0.1:6379> exists aa
(integer) 0
127.0.0.1:6379> rename a aa //重命名
OK
127.0.0.1:6379> exists aa
(integer) 1
127.0.0.1:6379> del aa //删除
(integer) 1
方法
- getset key value 返回旧值并设置新值。如果键不存在,就创建并赋值
- strset key 获取指定key的value值长度
- append key value 将新value内容追加到原先value值的后面,如果键存在就追加,如果不存在就等同于set key value
- getrange key start end 截取子字符串,左闭右闭,【start,end】
索引值从0开始,负数表示从字符串右边向左数起,-1表示最后的一个字符 - setrange key offset value 从offset处,将value值覆盖在原先对应位置的字符串内容上
127.0.0.1:6379> getset c abc // getset
"cc"
127.0.0.1:6379> strlen c //获取字符串长度
(integer) 3
127.0.0.1:6379> append c xyz
(integer) 6
127.0.0.1:6379> get c
"abcxyz"
127.0.0.1:6379> getrange c 1 3 //获取子字符串
"bcx"
127.0.0.1:6379> setrange c 1 1234 //覆盖部分字符串
(integer) 6
127.0.0.1:6379> get c
"a1234z"
步长的加减
虽然key和value都是字符串,但是value字符串里面要是数字的形式才能加减步长
127.0.0.1:6379> set a 10
OK
127.0.0.1:6379> incr a //增加一个步长,value值加一
(integer) 11
127.0.0.1:6379> decr a //减少一个步长,value值减一
(integer) 10
127.0.0.1:6379> incrby a 10 //增加指定的步长距离
(integer) 20
127.0.0.1:6379> decrby a 10 //减少指定的步长距离
(integer) 10
位图
位图不是真正的数据类型,只是在字符串类型中出现
一个字符串类型的值最多能存储512M字节的内容,1M等于1024k,1k等于1024byte,而1byte等于8bit,因此一个字符串类型的值最多有512x1024x1024x8位
比如现在存储了一个字符串 “ a ”,那么这个字符串的位图是
前面八位存放的是“ a ”的八位二进制,后面放着的512x1024x1024x8 - 8 位都是 0
在redis里面只有 1 才算数据占用内容,0是不占用内容的,所有即使有这么多的 0 也不会多占用内容
我们可以命令行中通过方法,来获取“ a ”的指定偏移量的位的内容
- setbit key offset value —— 设置某一位上的值
(1)offset偏移量,从0开始
(2)value不写,默认是0
(3)当key不存在时,会自动创建一个key - getbit key offset —— 获取指定偏移量对应的位置上的数值,0或1
127.0.0.1:6379> set k a
OK
127.0.0.1:6379> getbit k 0
(integer) 0
127.0.0.1:6379> getbit k 1
(integer) 1
127.0.0.1:6379> getbit k 2
(integer) 1
127.0.0.1:6379> getbit k 3
(integer) 0
127.0.0.1:6379> getbit k 4
(integer) 0
127.0.0.1:6379> getbit k 5
(integer) 0
127.0.0.1:6379> getbit k 6
(integer) 0
127.0.0.1:6379> getbit k 7
(integer) 1
查询到的结果是0110 0001 ,正是 a 的ASCII码值 97 对应的二进制数
既然可以这样查询到二进制内容,也可以通过修改对应的位的二进制数字,从而修改value值
127.0.0.1:6379> setbit k 6 1 //将value值的第6位修改为1
(integer) 0
127.0.0.1:6379> setbit k 7 0 //将value值的第6位修改为0
(integer) 1
127.0.0.1:6379> get k
"b"
修改过后,二进制内容变为 0110 0010 也就是 97 即字符串 ” b “
当字符串里面不止有一个字符时,比如value值为 ” ab “,那么其位图的前十六位就是 a 和 b 的八位二进制数拼接而成
也就是 0110 0001 0110 0010
- bitcount
BITCOUNT key 计算给定字符串中,被设置为 1 的比特位的数量
127.0.0.1:6379> bitcount k
(integer) 3 //0110 0001 里面一共有3个1
//可以给定区间,不过这个区间是用来划分几个字符在一个区间内
127.0.0.1:6379> set a aaaaaaaa
OK
127.0.0.1:6379> bitcount a //一个a有3个1,8个a一共24个1
(integer) 24
127.0.0.1:6379> bitcount a 0 3 // 这里的区间0 3是选中第0到第3个字符a,一共有4个a,所以12个1
(integer) 12
127.0.0.1:6379> bitcount a 0 7
(integer) 24
- bitpos
BITPOS key bit [ start ] [ end ] 返回位图中第一个值为 bit 的二进制位的位置
127.0.0.1:6379> bitpos k 1
(integer) 1 //0110 0001 里面1的第一次出现的位置是索引1位置
- bitop
BITOP operation destkey key [key …] 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上
operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种
AND —— 逻辑并 —— 1 and 1=1,1 and 0= 0,0 and 0= 0,0 and 1= 0
OR —— 或运算 —— 1 or 1= 1,1 or 0= 1,0 or 0= 0,0 or 1= 1
NOT —— 逻辑非 —— not 1 = 0,not 0 = 1
XOR —— 异或运算 —— 相同为0,不同为1
利用位图来统计用户登录天数
将用户id作为键值对的key值,后面的value值是一个String字符串,字符串内有一个位图
将位图的偏移量作为第几天,将对应位置的 1 表示已登录,0 表示未登录
这样用bitcount统计每个key值中的 1 的数量,即可统计用户登录天数
而第一天是指位图的偏移量 0,也就是第 0 位
//用户id为1001,设置第一天已登录,也就是设置偏移量为0的位置上值为1
127.0.0.1:6379> setbit 1001 0 1
(integer) 0
127.0.0.1:6379> setbit 1001 3 1
(integer) 0
127.0.0.1:6379> setbit 1001 5 1
(integer) 0
127.0.0.1:6379> setbit 1001 7 1
(integer) 0
127.0.0.1:6379> setbit 1001 12 1
(integer) 0
127.0.0.1:6379> bitcount 1001 //用户1001一共登录了5天
(integer) 5
这样只能统计某个用户的全部登录次数,那么如果想给定一个时间段,然后统计该时间段内的登录次数该怎么做?
之前说过,如果直接在bitcount后面给一个区间,那么是将几个字符包含在一起,也就是说
redis 的 setbit 修改的是 bit 位置,而 bitcount 检查的是 byte 位置,两者相差有 8 的倍数。
因此如果想求取第9天到第16天的全部登录次数的话,可以这样统计
127.0.0.1:6379> bitcount 1001 1 1
(integer) 1
127.0.0.1:6379> setbit 1001 14 1
(integer) 0
127.0.0.1:6379> setbit 1001 15 1 //在第16天用户也登录了
(integer) 0
127.0.0.1:6379> bitcount 1001 1 1 //第八天到第十六天一共登录了3次
(integer) 3
按天统计网站当天的活跃用户
以某一天作为key,然后以字符串为value值,字符串里面的位图中,偏移量代表用户id,位值表示是否登录
假设2月1号,有1001,1002,1003三位用户登录网站
2月2号有 1001,1002,1005 三位用户登录网站,现在要统计2月1号到2月2号的所有登录网站的用户数量
思路就是利用 OR 运算计算2月1号和2月2号的位图里的值,然后统计2月1号-2月2号的位图里面的 1 的数量
127.0.0.1:6379> setbit 02-01 1001 1
(integer) 0
127.0.0.1:6379> setbit 02-01 1002 1
(integer) 0
127.0.0.1:6379> setbit 02-01 1003 1
(integer) 0
127.0.0.1:6379> setbit 02-02 1001 1
(integer) 0
127.0.0.1:6379> setbit 02-02 1002 1
(integer) 0
127.0.0.1:6379> setbit 02-02 1005 1
(integer) 0
127.0.0.1:6379> bitop or 02-01~02-02 02-01 02-02
(integer) 126
127.0.0.1:6379> bitcount 02-01~02-02
(integer) 4
最后统计的结果为4,2月1号到2月2号期间,一共有4位用户登录了网站
同样的,这种思路也可以用于求取,两个用户的共同关注
比如张同学关注了用户 001,002,004
然后陈同学关注了用户 001,003,004
那么两个位图的值分别是,1101 和 1011,用 and 对两个数进行运算,结果为 1001
两人的共同关注是 001 和 004