中文文档 点击跳转.
一:基本命令
1.连接 redis
redis-cli -p **** -h ***.***.***.*** -a ******
-p + 端口号 -h + IP -a + 密码
输入ping 测试连接成功 #查看当前连接是否正常,正常返回PONG
2.简单介绍一下Redis中队Key的操作命令。最常用的命令!
[root@node1 ~]# redis-cli -p 7006 -h 192.168.51.174 -a ***** #登录
192.168.51.174:7006> ping #测试连接
PONG #连接成功
192.168.51.174:7006> keys * #获取所有key
(empty array)
192.168.51.174:7006> flushall # 清空所有数据库的键值对 flushdb:清空当前数据库中的键值对。
OK
192.168.51.174:7006> set name test # 设置一个key为name,值为test的数据
OK
192.168.51.174:7006> get name # 根据key拿值
"test"
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> set keyname keyvalue
OK
192.168.51.174:7006> keys *
1) "keyname"
192.168.51.174:7006> get keyname
"keyvalue"
192.168.51.174:7006> exists keyname #是否存在这个key
(integer) 1
192.168.51.174:7006> get kname
"kvalue"
192.168.51.174:7006> set kname1 kvalue1
OK
192.168.51.174:7006> keys *
1) "kname1"
2) "kname"
192.168.51.174:7006> MOVE kname1 1 # 删除当前库1的key为'kname1'的数据
(integer) 1
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> set kname kvalue
OK
192.168.51.174:7006> EXPIRE kname 20 #设置20秒超时
(integer) 1
192.168.51.174:7006> ttl kname
(integer) 16
192.168.51.174:7006> ttl kname
(integer) 10
192.168.51.174:7006> ttl kname
(integer) 8
192.168.51.174:7006> ttl kname
(integer) 6
192.168.51.174:7006> ttl kname
(integer) 1
192.168.51.174:7006> ttl kname
(integer) 0
192.168.51.174:7006> ttl kname
(integer) -2
192.168.51.174:7006> ttl kname
(integer) -2
192.168.51.174:7006>
二:Redis的五大数据类型
1.String类型
String是Redis中最常用的一种数据类型,也是Redis中最简单的一种数据类型。首先,表面上它是字符串,但其实他可以灵活的表示字符串、整数、浮点数3种值。Redis会自动的识别这3种值。
192.168.51.174:7006> clear
192.168.51.174:7006> set kstr vstr #设置数据,
#插入的数据中如果有空格的数据,请用""双引号或者用,隔开,否则会报错!
OK
192.168.51.174:7006> get kstr
"vstr"
192.168.51.174:7006> keys *
1) "kstr"
192.168.51.174:7006> EXISTS ksrt1 # 是否存在 不存在返回0
(integer) 0
192.168.51.174:7006> EXISTS kstr # 存在返回1
(integer) 1
192.168.51.174:7006> APPEND kstr addRange # 拼接字符串,并返回字符串长度
(integer) 12
192.168.51.174:7006> get kstr
"vstraddRange"
192.168.51.174:7006> strlen kstr #获取字符串长度
(integer) 12
192.168.51.174:7006> set kstr kvalue
OK
192.168.51.174:7006> get kstr
"kvalue"
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> set k 0 #创建一个数字类型数据
OK
192.168.51.174:7006> get k
"0"
192.168.51.174:7006> INCR k # 自增,相当于java中 i++
(integer) 1
192.168.51.174:7006> get k
"1"
192.168.51.174:7006> get k
"1"
192.168.51.174:7006> INCR k
(integer) 2
192.168.51.174:7006> INCR k
(integer) 3
192.168.51.174:7006> get k
"3"
192.168.51.174:7006> INCRBY k 10 #指定数量自增
(integer) 13
192.168.51.174:7006> get k
"13"
192.168.51.174:7006> INCRBY k 5
(integer) 18
192.168.51.174:7006> DECR k #自减
(integer) 17
192.168.51.174:7006> get k
"17"
192.168.51.174:7006> DECRBY k 7 # 指定数量自减
(integer) 10
192.168.51.174:7006> get k
"10"
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> set k "hello,my love"
OK
192.168.51.174:7006> get k
"hello,my love"
192.168.51.174:7006> GETRANGE k 6 13 #根据下标截取字符串
"my love"
192.168.51.174:7006> set k "hello,my love"
OK
192.168.51.174:7006> GETRANGE k 6 -1 #下标不能省略, -1代表到结尾
"my love"
192.168.51.174:7006> set k 1111111111111111111
OK
192.168.51.174:7006> get k
"1111111111111111111"
192.168.51.174:7006> SETRANGE k 5 33333333 # 替换
(integer) 19
192.168.51.174:7006> get k
"1111133333333111111"
192.168.51.174:7006> EXPIRE k4 20 # 给不存在的key设置超时返回0
(integer) 0
192.168.51.174:7006> ttl k4 # -2即代表不存在
(integer) -2
192.168.51.174:7006> EXPIRE k 20 #设置超时成功返回1
(integer) 1
192.168.51.174:7006> ttl k # 剩余14s超时
(integer) 14
192.168.51.174:7006> ttl k
(integer) 4
192.168.51.174:7006> ttl k
(integer) 1
192.168.51.174:7006> ttl k # 已超时,不存在
(integer) -2
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> set k 1111111111111
OK
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> GETSET k 1111111111 #先获取,再赋值
(nil)
192.168.51.174:7006> get k
"1111111111"
192.168.51.174:7006> getset k 3434343433
"1111111111"
192.168.51.174:7006> get k
"3434343433"
192.168.51.174:7006> mset k1 v1 k2 2 k3 v3 k4 4 #批量设置
OK
192.168.51.174:7006> keys *
1) "k3"
2) "k4"
3) "k2"
4) "k1"
192.168.51.174:7006> mget k1 k2 k3 k4 #批量获取
1) "v1"
2) "2"
3) "v3"
4) "4"
192.168.51.174:7006>
2.List(列表)
如果key 不存在,创建新的链表
如果key存在,新增内容
如果移除了所有值,空链表,也代表不存在!
在两边插入或者改动值,效率最高! 中间元素相对来说效率会低一点
lpush(左插入)、lrange(查询集合)、rpush(右插入)
lpop(左移除)、rpop(右移除)
lindex(查询指定下标元素)、llen(获取集合长度)
lrem(根据value移除指定的值)
ltrim(截取元素)、rpoplpush(移除指定集合中最后一个元素到一个新的集合中)
lset(更新)、linsert操作
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> lpush k v1 #新增一个集合k 添加元素v1
(integer) 1
192.168.51.174:7006> lpush k v2 #添加元素v2
(integer) 2
192.168.51.174:7006> lpush k v3
(integer) 3
192.168.51.174:7006> lpush k v4
(integer) 4
192.168.51.174:7006> lpush k v5
(integer) 5
192.168.51.174:7006> lpush k v5
(integer) 6
192.168.51.174:7006> lpush k v5
(integer) 7
192.168.51.174:7006> lrange k 0 -1 # 查询所有元素 0是起始下标,-1是结束下标,
1) "v5"
2) "v5"
3) "v5"
4) "v4"
5) "v3"
6) "v2"
7) "v1"
192.168.51.174:7006> lpush k1 v1 v2 v3 v4 v5 v5 v5 v5 #批量添加
(integer) 8
192.168.51.174:7006> lrange k1 0 -1 #查询集合所有元素
1) "v5"
2) "v5"
3) "v5"
4) "v5"
5) "v4"
6) "v3"
7) "v2"
8) "v1"
192.168.51.174:7006> llen k # 获取长度
(integer) 8
192.168.51.174:7006> lindex k 0 #根据下标获取元素
"v5"
192.168.51.174:7006> lindex k 4 #根据下标获取元素
"v3"
192.168.51.174:7006> lrange k 0 0 #指定元素查询
1) "v5"
192.168.51.174:7006> lrange k 0 4 #指定范围获取
1) "v5"
2) "v5"
3) "v5"
4) "v4"
5) "v3"
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> lpush k v1 v2 v3 v4 v5
(integer) 5
192.168.51.174:7006> rpush k1 v1 v2 v3 v4 v5 #右插入,从集合末尾插入 方向与lpush相反
(integer) 5
192.168.51.174:7006> lrange k 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
5) "v1"
192.168.51.174:7006> lrange k1 0 -1
1) "v1"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> lpush k v0 v1 v2 v3 v4 v5 v6 v7 v8 v9
(integer) 10
192.168.51.174:7006> lrange k 0 -1
1) "v9"
2) "v8"
3) "v7"
4) "v6"
5) "v5"
6) "v4"
7) "v3"
8) "v2"
9) "v1"
10) "v0"
192.168.51.174:7006> lpop k #返回第一个元素并移除
"v9"
192.168.51.174:7006> lpop k 2 #移除前两个元素
1) "v8"
2) "v7"
192.168.51.174:7006> lrange k 0 -1
1) "v6"
2) "v5"
3) "v4"
4) "v3"
5) "v2"
6) "v1"
7) "v0"
192.168.51.174:7006> rpop k #移除最后一个元素
"v0"
192.168.51.174:7006> rpop k 3 # 移除后三个元素
1) "v1"
2) "v2"
3) "v3"
192.168.51.174:7006> lrange k 0 -1
1) "v6"
2) "v5"
3) "v4"
192.168.51.174:7006> lrange k 0 -1
1) "v6"
2) "v5"
3) "v4"
192.168.51.174:7006> rpush k v3 v2 v1 v0
(integer) 7
192.168.51.174:7006> lrange k 0 -1
1) "v6"
2) "v5"
3) "v4"
4) "v3"
5) "v2"
6) "v1"
7) "v0"
192.168.51.174:7006> lpush k v7 v8 v9
(integer) 10
192.168.51.174:7006> lrange k 0 -1
1) "v9"
2) "v8"
3) "v7"
4) "v6"
5) "v5"
6) "v4"
7) "v3"
8) "v2"
9) "v1"
10) "v0"
192.168.51.174:7006> LREM k 1 v9 #移除集合k中一个值为v9的元素
(integer) 1
192.168.51.174:7006> lrange k 0 -1
1) "v8"
2) "v7"
3) "v6"
4) "v5"
5) "v4"
6) "v3"
7) "v2"
8) "v1"
9) "v0"
192.168.51.174:7006> lpush k v10 v10 v10 v10
(integer) 13
192.168.51.174:7006> lrange k 0 -1
1) "v10"
2) "v10"
3) "v10"
4) "v10"
5) "v8"
6) "v7"
7) "v6"
8) "v5"
9) "v4"
10) "v3"
11) "v2"
12) "v1"
13) "v0"
192.168.51.174:7006> LREM k 3 v10 #移除集合k中三个值为v10的元素
(integer) 3
192.168.51.174:7006> lrange k 0 -1
1) "v10"
2) "v8"
3) "v7"
4) "v6"
5) "v5"
6) "v4"
7) "v3"
8) "v2"
9) "v1"
10) "v0"
192.168.51.174:7006> LTRIM k 1 -1 #从下标1开始截取至结尾
OK
192.168.51.174:7006> lrange k 0 -1
1) "v8"
2) "v7"
3) "v6"
4) "v5"
5) "v4"
6) "v3"
7) "v2"
8) "v1"
9) "v0"
192.168.51.174:7006> RPOPLPUSH k k1 #移除最后一个元素并添加到k1集合中
"v0"
192.168.51.174:7006> lrange k1 0 -1
1) "v0"
192.168.51.174:7006> lrange k 0 -1
1) "v8"
2) "v7"
3) "v6"
4) "v5"
5) "v4"
6) "v3"
7) "v2"
8) "v1"
192.168.51.174:7006> lset k 3 value5 #对集合k中下标为3的元素重新赋值
OK
192.168.51.174:7006> lrange k 0 -1
1) "v8"
2) "v7"
3) "v6"
4) "value5"
5) "v4"
6) "v3"
7) "v2"
8) "v1"
192.168.51.174:7006> LINSERT k after v6 supper6 #集合k中元素v6后面添加supper6
(integer) 9
192.168.51.174:7006> lrange k 0 -1
1) "v8"
2) "v7"
3) "v6"
4) "supper6"
5) "value5"
6) "v4"
7) "v3"
8) "v2"
9) "v1"
192.168.51.174:7006> LINSERT k before v6 supper7 #集合k中元素v6前面添加supper7
(integer) 10
192.168.51.174:7006> lrange k 0 -1
1) "v8"
2) "v7"
3) "supper7"
4) "v6"
5) "supper6"
6) "value5"
7) "v4"
8) "v3"
9) "v2"
10) "v1"
192.168.51.174:7006>
3.Set(集合)元素唯一不重复
sadd(添加)、smembers(查看所有元素)、sismember(判断是否存在)、scard(查看长度)、srem(移除指定元素)、srandmember(抽随机)、spop(随机删除元素)、smove(移动指定元素到新的集合中)、sdiff(差集)、sinter(交集)、sunion(并集)
192.168.51.174:7006> MOVE k 1
(integer) 1
192.168.51.174:7006> sadd k v1 v2 v3 v4 v5 # 添加set集合元素
(integer) 5
192.168.51.174:7006> SMEMBERS k #展示元素
1) "v1"
2) "v4"
3) "v3"
4) "v2"
5) "v5"
192.168.51.174:7006> SISMEMBER k v1 #是否存在元素v1 存在返回1
(integer) 1
192.168.51.174:7006> SISMEMBER k v7 #不存在返回0
(integer) 0
192.168.51.174:7006> SCARD k
(integer) 5
192.168.51.174:7006> smembers k
1) "v1"
2) "v4"
3) "v5"
4) "v2"
5) "v3"
192.168.51.174:7006> srem k v3 #删除元素
(integer) 1
192.168.51.174:7006> SMEMBERS k
1) "v1"
2) "v4"
3) "v5"
4) "v2"
192.168.51.174:7006> sadd k v6 v7 v8 v9
(integer) 4
192.168.51.174:7006> SMEMBERS k
1) "v8"
2) "v1"
3) "v9"
4) "v7"
5) "v4"
6) "v5"
7) "v6"
8) "v2"
192.168.51.174:7006> SRANDMEMBER k #随机抽取一个值
"v5"
192.168.51.174:7006> SRANDMEMBER k 1 #随机抽取一个值
1) "v2"
192.168.51.174:7006> SRANDMEMBER k 3 #随机抽取三个值
1) "v4"
2) "v5"
3) "v2"
192.168.51.174:7006> SMEMBERS k
1) "v8"
2) "v1"
3) "v9"
4) "v7"
5) "v4"
6) "v5"
7) "v6"
8) "v2"
192.168.51.174:7006> spop k 1 # 随机删除一个元素
1) "v5"
192.168.51.174:7006> SMEMBERS k
1) "v8"
2) "v1"
3) "v9"
4) "v7"
5) "v4"
6) "v6"
7) "v2"
192.168.51.174:7006> smove k k1 v2 #移动指定元素到新set
(integer) 1
192.168.51.174:7006> SMEMBERS k1
1) "v2"
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> sadd k 0 1 2 3 4 5 6
(integer) 7
192.168.51.174:7006> sadd k1 3 4 5 6 7 8 9
(integer) 7
192.168.51.174:7006> SMEMBERS k
1) "0"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
7) "6"
192.168.51.174:7006> SMEMBERS k1
1) "3"
2) "4"
3) "5"
4) "6"
5) "7"
6) "8"
7) "9"
192.168.51.174:7006> SDIFF k k1 #获取 k 与 k1 的差集,可以是多个set
1) "0"
2) "1"
3) "2"
192.168.51.174:7006> SDIFF k1 k #获取 k1 与 k 的差集,可以是多个set
1) "7"
2) "8"
3) "9"
192.168.51.174:7006> sinter k1 k #查询指定的set之间的交集,可以是多个set
1) "3"
2) "4"
3) "5"
4) "6"
192.168.51.174:7006> SUNION k k1 #查询指定的set之间的并集,可以是多个set
1) "0"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
7) "6"
8) "7"
9) "8"
10) "9"
192.168.51.174:7006>
4.Hash(哈希)
hset(添加hash)、hget(查询)、hgetall(查询所有)、hdel(删除hash中指定的值)、hlen(获取hash的长度)、hexists(判断key是否存在)、②hkeys(获取所有key)、hvals(获取所有value)、hincrby(给值加增量)、hsetnx(存在不添加)
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> hset k name KSJD age 18 gender 1 #创建hash对象k
(integer) 3
192.168.51.174:7006> hget k name #获取k对象中元素值
"KSJD"
192.168.51.174:7006> hget k age
"18"
192.168.51.174:7006> HGETALL k #获取k中所有的值,包含key
1) "name"
2) "KSJD"
3) "age"
4) "18"
5) "gender"
6) "1"
192.168.51.174:7006> hset k tec java #添加元素
(integer) 1
192.168.51.174:7006> HGETALL k
1) "name"
2) "KSJD"
3) "age"
4) "18"
5) "gender"
6) "1"
7) "tec"
8) "java"
192.168.51.174:7006> HDEL k age tec #删除元素 可以单个也可以多个,空格隔开
(integer) 2
192.168.51.174:7006> HGETALL k
1) "name"
2) "KSJD"
3) "gender"
4) "1"
192.168.51.174:7006> hlen k # 获取长度
(integer) 2
192.168.51.174:7006> hexists k name #判断是否存在该字段 ,存在返回1
(integer) 1
192.168.51.174:7006> hexists k age #判断是否存在该字段,不存在返回0
(integer) 0
192.168.51.174:7006>
5.zSet(有序集合)
zadd(添加)、zrange(查询)、zrangebyscore(排序小-大)、zrevrange(排序大-小)、zrangebyscore withscores(查询所有值包含key),zrem(移除元素)、zcard(查看元素个数)、zcount(查询指定区间内的元素个数)
192.168.51.174:7006> clear
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> zadd k 1 one 2 two 3 three 4 four 5 five # 创建zset
(integer) 5
192.168.51.174:7006> zrange k 0 -1 # #查询所有的值
1) "one"
2) "two"
3) "three"
4) "four"
5) "five"
192.168.51.174:7006> ZRANGEBYSCORE k -inf +inf #将zset的值根据key来从小到大排序并输出,
#-inf 负无穷 +inf 正无穷
1) "one"
2) "two"
3) "three"
4) "four"
5) "five"
192.168.51.174:7006> ZRANGEBYSCORE k 0 1 #只查询key<=1的值并且排序从小到大
1) "one"
192.168.51.174:7006> ZRANGEBYSCORE k 2 4 #查询2<=key<=4的值并且排序从小到大
1) "two"
2) "three"
3) "four"
192.168.51.174:7006> ZREVRANGE k 1 -1
1) "four"
2) "three"
3) "two"
4) "one"
192.168.51.174:7006> ZREVRANGE k 0 -1
1) "five"
2) "four"
3) "three"
4) "two"
5) "one"
192.168.51.174:7006> ZRANGEBYSCORE k -inf +inf withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "four"
8) "4"
9) "five"
10) "5"
192.168.51.174:7006> zrange k 0 -1
1) "two"
2) "three"
3) "four"
4) "five"
192.168.51.174:7006> zcard k #获取长度
(integer) 4
192.168.51.174:7006> zcount k 1 10 #获取
(integer) 4
192.168.51.174:7006> zcount k 2 4 #指定区间内的元素个数
(integer) 3
192.168.51.174:7006> zcount k 2 5
(integer) 4
192.168.51.174:7006>
三: 三大特殊数据类型的学习和理解
1.Geospatial: 地理位置
城市经纬度查询: 经纬度查询
注意点1:两极无法直接添加
注意点2:有效的经度从-180度到180度。
注意点3:有效的纬度从-85.05112878度到85.05112878度。
注意点4:m 为米。km 为千米。mi 为英里。ft 为英尺。
geoadd(添加)、geopos(查看)、geodist(计算距离)、georadius(查询附近位置)、georadiusbymember (查找指定元素指定范围内的元素)、geohash (返回经纬度的hash值)、zrange、zrem(使用zset命令操作geo)
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> clear
192.168.51.174:7006> geoadd city 118.8921 31.32751 nanjing 117.30794 31.79322 hefei 102.82147 24.88554 kunming 91.13775 29.65262 lasa 116.23128 40.22077 beijing 106.54041 29.40268 chongqing # 插入城市坐标
(integer) 6
192.168.51.174:7006> zrange city 0 -1 #查看所有城市,和zset命令一致
1) "lasa"
2) "kunming"
3) "chongqing"
4) "hefei"
5) "nanjing"
6) "beijing"
192.168.51.174:7006> GEOPOS city nanjing #查看城市具体坐标
1) 1) "118.89209836721420288"
2) "31.32750976275760735"
192.168.51.174:7006> GEOPOS city beijing nanjing #查看多个城市具体坐标
1) 1) "116.23128265142440796"
2) "40.22076905438526495"
2) 1) "118.89209836721420288"
2) "31.32750976275760735"
192.168.51.174:7006> GEODIST city beijing nanjing #计算城市之间的距离 m
"1017743.1413"
192.168.51.174:7006> GEODIST city beijing nanjing km #km单位
"1017.7431"
192.168.51.174:7006> zrange city 0 -1
1) "lasa"
2) "kunming"
3) "chongqing"
4) "hefei"
5) "nanjing"
6) "beijing"
192.168.51.174:7006> GEORADIUS city 117.10613 36.70494 500 km #获取该经纬度500km以内的坐标
1) "beijing"
192.168.51.174:7006> GEORADIUS city 117.10613 36.70494 1000 km
1) "beijing"
2) "hefei"
3) "nanjing"
192.168.51.174:7006> GEORADIUS city 117.10613 36.70494 1000 km withcoord #详情
1) 1) "beijing"
2) 1) "116.23128265142440796"
2) "40.22076905438526495"
2) 1) "hefei"
2) 1) "117.30793744325637817"
2) "31.79321915080526395"
3) 1) "nanjing"
2) 1) "118.89209836721420288"
2) "31.32750976275760735"
192.168.51.174:7006> GEORADIUS city 117.10613 36.70494 1000 km withcoord withdist
1) 1) "beijing"
2) "398.3994"
3) 1) "116.23128265142440796"
2) "40.22076905438526495"
2) 1) "hefei"
2) "546.6271"
3) 1) "117.30793744325637817"
2) "31.79321915080526395"
3) 1) "nanjing"
2) "620.3231"
3) 1) "118.89209836721420288"
2) "31.32750976275760735"
192.168.51.174:7006> GEORADIUS city 117.10613 36.70494 1000 km withcoord withdist withhash
1) 1) "beijing"
2) "398.3994"
3) (integer) 4069896088584598
4) 1) "116.23128265142440796"
2) "40.22076905438526495"
2) 1) "hefei"
2) "546.6271"
3) (integer) 4052763834193093
4) 1) "117.30793744325637817"
2) "31.79321915080526395"
3) 1) "nanjing"
2) "620.3231"
3) (integer) 4054278565840695
4) 1) "118.89209836721420288"
2) "31.32750976275760735"
192.168.51.174:7006> GEORADIUSBYMEMBER city beijing 1000 km #距离北京1000km以内的城市
1) "beijing"
2) "hefei"
192.168.51.174:7006> zrange city 0 -1
1) "lasa"
2) "kunming"
3) "chongqing"
4) "hefei"
5) "nanjing"
6) "beijing"
192.168.51.174:7006> zrem city lasa #根据名称删除元素
(integer) 1
192.168.51.174:7006> zrange city 0 -1
1) "kunming"
2) "chongqing"
3) "hefei"
4) "nanjing"
5) "beijing"
192.168.51.174:7006>
2.Hyperloglog: 基数
但是再Redis中,可能会有一定的误差性。 官方给出的误差率是0.81%。
Hyperloglog的优点: 占用的内存是固定的,2^64个元素,相当于只需要12kb的内存即可。效率极高!
pfadd(添加数据集)、pfcount(统计数据集)、pfmegre(合并数据集-自动去重)
192.168.51.174:7006> pfadd k 1 2 3 4 5 6 7 #添加数据
(integer) 1
192.168.51.174:7006> PFCOUNT k #统计数据
(integer) 7
192.168.51.174:7006> pfadd k1 5 6 7 8 9 0
(integer) 1
192.168.51.174:7006> PFCOUNT k1
(integer) 6
192.168.51.174:7006> PFMERGE k2 k k1 #合并数据成为一个新数据,自动去重
OK
192.168.51.174:7006> PFCOUNT k2
(integer) 10
192.168.51.174:7006>
3.Bitmap: 位存储
Bitmap 位图,数据结构! 都是操作二进制位来进行记录,就只有0 和 1 两个状态!
①setbit(添加)、getset(获取)、bitcount(统计)操作
192.168.51.174:7006> flushall
OK
192.168.51.174:7006> setbit k 1 1 #添加 1 为 1
(integer) 0
192.168.51.174:7006> GETBIT k 1 #获取 1
(integer) 1
192.168.51.174:7006> setbit k 2 0
(integer) 0
192.168.51.174:7006> GETBIT k 2
(integer) 0
192.168.51.174:7006> SETBIT k 3 1
(integer) 0
192.168.51.174:7006> SETBIT k 4 1
(integer) 0
192.168.51.174:7006> SETBIT k 5 1
(integer) 0
192.168.51.174:7006> BITCOUNT k #统计k
(integer) 4
192.168.51.174:7006>
JAVA
SpringBoot整合Redis
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.7.RELEASE</version>
</dependency>
<!--序列化-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
<scope>compile</scope>
</dependency>
<!--lombok,自动生成set、get等方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>compile</scope>
</dependency>
server:
port: 8080
spring:
# redis
redis:
host: 192.168.51.174 #IP
port: 7006 # 端口
password: ********
database: 1
#lettuce:
timeout: 7200s # 连接超时时间
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
redisTemplate #操作不同的数据类型,api和我们的指令是一样的
opsForValue #操作字符串 类似String
opsForList #操作List 类似List
opsForSet #操作set
opsForHash #操作hash
opsForZSet #操作zset
opsForGeo #操作geo
opsForHyperLogLog #操作HyperLogLog
除了进本的操作,我们常用的方法都可以直接通过redisTemplate操作,比如事务,和基本的 CRUD
获取redis的连接对象
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.flushDb();
connection.flushAll();
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public final class RedisUtils {
@Resource
private RedisTemplate<String, Object> redisTemplate;
private static final Long LOCK_EXPIRE = 1000L * 60; // 默认锁时间 1分钟
/**
* 分布式锁,默认锁定1分钟
*
* @param key key值
* @return 是否获取到
*/
public boolean lock(String key) {
return lock(key, LOCK_EXPIRE);
}
/**
* redis分布式锁
*
* @param key 锁定的key
* @param lockExpire 过期时间
* @param timeUnit 时间单位
* @return
*/
public boolean lock(String key, Long lockExpire, TimeUnit timeUnit) {
return lock(key, timeUnit.toMillis(lockExpire));
}
/**
* redis分布式锁 成功加锁返回true,锁已存在或加锁失败返回false
*
* @param key 锁定的key
* @param lockExpire 过期时间,单位为毫秒
* @return
*/
public boolean lock(String key, Long lockExpire) {
return setNx(key, lockExpire, lockExpire);
}
/**
* 模糊查询出所有合适的 keys (键务必为String格式)
*
* @param prefix 键
* @return
*/
public Set<String> likeKeys(String prefix) {
try {
return redisTemplate.keys(prefix + "*");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(毫秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.MILLISECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(毫秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
}
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(毫秒 time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean setKey(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入, 不存在放入,存在返回
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean setNx(String key, Object value) {
try {
redisTemplate.opsForValue().setIfAbsent(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间,不存在放入,存在返回
*
* @param key 键
* @param value 值
* @param time 时间(毫秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean setNx(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.MILLISECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> getHash(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object getHash(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean setHash(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean setHash(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean setHash(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean setHash(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void delHash(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hasHashKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public double hashIncr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public double hashDecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> getSetKey(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean hasSetKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long setSetKey(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long setSetKey(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long getSetKeySize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long removeSet(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
// ===============================list=================================
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long getListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> getList(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object getList(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean setListRight(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean setListRight(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean setListRight(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean setListRight(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean updateListIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long removeList(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}