resdis 简介
redis 是用C 语言开发的一个开源的高性能键值对(key-value)数据库
redis 没有windows官方,第三方版本下载 windows下载
数据类型
redis 数据类型
五大数据类型:
string (字符串)
hash(哈希)
list(列表)
set(集合)
zset(有序集合)
三种特殊数据类型:
geospatial (地理位置)
hyperloglog
bitmaps
string (字符串)
存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
存储数据的格式:一个存储空间保存一个数据
存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用
基本操作
添加、修改数据
set key value
eg:
127.0.0.1:6379> set name jack
OK
获取数据
get key
eg:
127.0.0.1:6379> get name
"jack"
删除数据
del key
eg:
127.0.0.1:6379> del name
(integer) 1
添加、修改多个数据
mset key1 value1 key2 value2 ...
eg:
127.0.0.1:6379> mset name1 jack name2 bob
OK
msetnx:不存在时设置多个数据
msetnx key1 value1 key2 value2 ...
eg:
127.0.0.1:6379> msetnx k1 v1 k2 v2 k3 v3
(integer) 1
127.0.0.1:6379> msetnx k1 v1 k4 v4 # msetnx 是一个原子性的操作,要么一起成功,要么一起失败
(integer) 0
获取多个数据
mget key1 key2 ...
eg:
127.0.0.1:6379> mget name1 name2
1) "jack"
2) "bob"
获取数据字符个数(字符串长度)
strlen key
eg:
127.0.0.1:6379> strlen name
(integer) 4
追加信息到原始信息后部(如果原始信息存在就追加,否则新建)
append key value
eg:
127.0.0.1:6379> append name wang
(integer) 8
截取字符串
getrange key start end
eg:
127.0.0.1:6379> set key1 "hello,world"
OK
127.0.0.1:6379> getrange key1 0 4
"hello"
127.0.0.1:6379> getrange key1 0 -1
"hello,world"
getset: 先获取再设置
如果不存在值,则返回 nil,如果存在值,获取原来的值,并设置新的值
getset key value
eg:
127.0.0.1:6379> getset n 1
(nil)
127.0.0.1:6379> getset n 2
"1"
127.0.0.1:6379> get n
"2"
替换字符串
setrange key offset value
eg:
127.0.0.1:6379> setrange key1 1 xxx
(integer) 11
127.0.0.1:6379> get key1
"hxxxo,world"
string 作为数值操作
设置数值数据增加指定范围的值
incr key
incrby key increment
incrbyfloat key increment
eg:
127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incrby num 2
(integer) 4
127.0.0.1:6379> incrbyfloat num 1.2
"5.2"
设置数值数据减少指定范围的值
decr key
decrby key increment
eg:
127.0.0.1:6379> set num 5
OK
127.0.0.1:6379> decr num
(integer) 4
127.0.0.1:6379> decrby num 2
(integer) 2
检测key 是否存在
exists key
eg:
127.0.0.1:6379> set name jack
OK
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
flushdb: 执行删除在某个db环境下执行的话,只删除当前db的数据
flushall:删除所有现有的数据库
eg:
127.0.0.1:6379> keys *
1) "mylist"
2) "list"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty list or set)
string 在redis 内部存储默认就是一个字符串,当遇到增减类操作 incr
、decr
时会转成数值型进行计算。
redis 所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响。
注意:按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis 数值上限范围,将报错。9223372036854775807 (java 中long 型数据最大值,Long.MAX_VALUE)
设置数据指定时间
设置数据过期时间
setex key seconds value
psetex key milliseconds value
查询到期时间
ttl key
eg:
127.0.0.1:6379> setex name 10 jack
OK
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> get name
"jack"
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> psetex name 10000 jack
OK
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> get name
"jack"
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)
setnx: 不存在再设置 (分布式锁中经常使用)
setnx key value
eg:
127.0.0.1:6379> setnx mykey redis
(integer) 1
127.0.0.1:6379> setnx mykey java # 存在则设置失败
(integer) 0
127.0.0.1:6379> get mykey
"redis"
应用场景
在redis 中为大V用户设定用户信息,以用户主键和属性值作为key,后台设定定时刷新策略即可
// eg: user:id:1321432423:fans -> 13313123
127.0.0.1:6379> set user:id:1321432423:fans 13313123
OK
// eg: user:id:1321432423:blog -> 808
127.0.0.1:6379> set user:id:1321432423:blog 808
OK
// eg: user:id:1321432423:focus -> 108
127.0.0.1:6379> set user:id:1321432423:focus 108
OK
在redis 中以json 格式存储大V 用户信息,定时刷新(也可以使用hash类型)
// eg: user:id:1321432423 -> {id:1321432423,name:"vname",fans:13313123,blogs:808,focus:108}
127.0.0.1:6379>set user:id:1321432423 '{id:1321432423,name:"vname",fans:13313123,blogs:808,focus:108}'
OK
key 的设置约定
数据库中的热点数据key 命名规范
表名 | 主键名 | 主键值 | 字段名 | |
---|---|---|---|---|
eg1: | order: | id: | 123113231 | :name |
eg2: | equip: | id: | 1321432423 | :type |
eg3: | news: | id: | 2020001313 | :title |
string 使用场景:
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储
hash(哈希)
新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
需要的存储结构:一个存储空间保存多个键值对数据
hash 类型:底层使用哈希表结构实现数据存储
基本操作
添加、修改数据
hset key field value
eg:
127.0.0.1:6379> hset myhash name jack
(integer) 1
127.0.0.1:6379> hset myhash age 18
(integer) 1
获取数据
hget key field
hgetall key
eg:
127.0.0.1:6379> hget myhash name
"jack"
127.0.0.1:6379> hget myhash age
"18"
127.0.0.1:6379> hgetall myhash
1) "name"
2) "jack"
3) "age"
4) "18"
删除数据
hdel key field1 [field2]
eg:
127.0.0.1:6379> hdel myhash name age
(integer) 2
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
添加、修改多个数据
hmset key field1 value1 field2 value2 ...
eg:
127.0.0.1:6379> hmset myhash field1 hello field2 world
OK
获取多个数据
hmget key field1 field2 ...
eg:
127.0.0.1:6379> hmget myhash field1 field2
1) "hello"
2) "world"
获取哈希表中字段的数量
hlen key
eg:
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hlen myhash
(integer) 2
获取哈希表中是否存在指定的字段
hexists key field
eg:
127.0.0.1:6379> hexists myhash field1
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
扩展操作
获取哈希表中所有的字段名或字段值
hkeys key
hvals key
eg:
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "field2"
127.0.0.1:6379> hvals myhash
1) "hello"
2) "world"
设置指定字段的数值数据增加指定范围的值
hincrby key field increment
hincrbyfloat key field increment
eg:
127.0.0.1:6379> hset myhash num 3
(integer) 1
127.0.0.1:6379> hincrby myhash num 5
(integer) 8
127.0.0.1:6379> hget myhash num
"8"
127.0.0.1:6379> hincrby myhash num -1
(integer) 7
127.0.0.1:6379> hget myhash num
"7"
127.0.0.1:6379> hincrbyfloat myhash num 0.02
"7.02"
127.0.0.1:6379> hget myhash num
"7.02"
127.0.0.1:6379> hincrby myhash num 2 # 如果值不是整数则保错
(error) ERR hash value is not an integer
127.0.0.1:6379> hincrbyfloat myhash num -0.01
"7.01"
添加数据,如果没有,就添加,有数据不添加
hsetnx key field value
eg:
127.0.0.1:6379> hsetnx myhash field5 6 # 如果不存在则设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field5 5 # 如果存在则不能设置
(integer) 0
注意事项
hash 类型下的 value 只能存储字符串,不允许存储其他数据类型,不存在嵌套现象,如果数据未获取到,对应的值(nil)
每个hash 可以存储 个键值对
hash 类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash 设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用
hgetall 操作可以获取全部属性,如果内部field 过多,遍历整体数据效率就会很低,有可能成为数据访问瓶颈。
list (列表)
数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
list 类型:保存多个数据,底层使用双向链表存储结构实现
基本操作
添加、修改数据
lpush key value1 [value2] ...
rpush key value1 [va;ue2] ...
eg:
127.0.0.1:6379> lpush list 1
(integer) 1
127.0.0.1:6379> lpush list 2
(integer) 2
127.0.0.1:6379> lpush list 3
(integer) 3
127.0.0.1:6379> rpush list 4
(integer) 4
127.0.0.1:6379> rpush list 5
(integer) 5
获取数据
lrange key start stop
lindex key index
llen key
eg:
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
4) "4"
5) "5"
127.0.0.1:6379> lindex list 2
"1"
127.0.0.1:6379> llen liist
(integer) 5
获取并移除数据
lpop key
rpop key
eg:
127.0.0.1:6379> lpop list
"3"
127.0.0.1:6379> rpop list
"5"
获取下标数据
lindex key index
eg:
127.0.0.1:6379> lindex list 1
"1"
移除指定数据
lrem key count value
eg:
127.0.0.1:6379> lrem list 1 1
(integer) 1
127.0.0.1:6379> rpush list 3 5 6 1 3
(integer) 7
127.0.0.1:6379> lrange list 0 -1
1) "2"
2) "4"
3) "3"
4) "5"
5) "6"
6) "1"
7) "3"
127.0.0.1:6379> lrem list 2 3
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "2"
2) "4"
3) "5"
4) "6"
5) "1"
截取数据
ltrim key start stop
eg:
list // 1 2 3 4 5
127.0.0.1:6379> ltrim list 1 2
OK
127.0.0.1:6379> lrange list 0 -1
1) "2"
2) "3"
rpoplpush:移除最后一个元素并添加到新的列表中
rpoplpush source destination
eg:
list // 1 2 3
127.0.0.1:6379> rpoplpush list mylist
"3"
127.0.0.1:6379> lrange list 0 -1
1) "1"
2) "2"
127.0.0.1:6379> lrange mylist 0 -1
1) "3"
lset: 将列表中指定下标的值替换为新值,更新操作
lset key index value
eg:
127.0.0.1:6379> exists list # 判断这个列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item # 如果不存在列表,更新会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item # 如果列表存在,更新当前下标的值
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 item1 # 如果下标不存在,则报错
(error) ERR index out of range
linsert: 将某个具体的值插入到列的某个元素前面或后面
linsert key BEFORE|AFTER pivot value
eg:
127.0.0.1:6379> lrange list 0 -1
1) "item1"
2) "item2"
3) "item3"
127.0.0.1:6379> linsert list before item2 item5
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "item1"
2) "item5"
3) "item2"
4) "item3"
127.0.0.1:6379> linsert list after item2 item6
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "item1"
2) "item5"
3) "item2"
4) "item6"
5) "item3"
扩展操作
规定时间内获取并移除数据
blpop key1 [key2] timeout
brpop key1 [key2] timeout
eg:
127.0.0.1:6379> lrange list 0 -1
1) "item1"
2) "item5"
3) "item2"
4) "item6"
5) "item3"
127.0.0.1:6379> blpop list 10
1) "list"
2) "item1"
127.0.0.1:6379> lrange list 0 -1
1) "item5"
2) "item2"
3) "item6"
4) "item3"
127.0.0.1:6379> brpop list 10
1) "list"
2) "item3"
127.0.0.1:6379> lrange list 0 -1
1) "item5"
2) "item2"
3) "item6"
注意事项
list 中保存的数据都是 string 类型的,数据总容量是有限的,最多 个元素(4294967295)
list 具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作(先进先出 lpush rpop),或以栈的形式进行入栈出栈操作(先进后出 lpush lpop)
获取全部数据操作结束索引设置为-1
list 可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载
set (集合)
新的存储需求:存储大量的数据,在查询方面提供更高的效率
需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
set类型:与hash存储结构完全相同,仅存储键,不存储值(nill),并且值是不允许重复的
基本操作
添加数据
sadd key member1 [member2]
eg:
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
获取全部数据
smembers key
eg:
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
删除数据
srem key member [member ...]
eg:
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
3) "item"
127.0.0.1:6379> srem myset item
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
获取集合数据总量
scard key
eg:
127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> sadd myset hello
(integer) 0
127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> sadd myset item
(integer) 1
127.0.0.1:6379> scard myset
(integer) 3
判断集合中是否包含指定数据
sismember key member
eg:
127.0.0.1:6379> sismember myset hello
(integer) 1
127.0.0.1:6379> sismember myset value
(integer) 0
扩展操作
随机获取集合中指定数量的数据
srandmember key [count]
eg:
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
127.0.0.1:6379> sadd myset 1 2 3 4 5 6 7 8 9 10
(integer) 10
127.0.0.1:6379> srandmember myset # 随机抽出一个元素
"world"
127.0.0.1:6379> srandmember myset
"1"
127.0.0.1:6379> srandmember myset
"8"
127.0.0.1:6379> srandmember myset 3 # 随机抽出指定个数的元素
1) "6"
2) "7"
3) "5"
127.0.0.1:6379> srandmember myset 3
1) "9"
2) "10"
3) "5"
随机获取集合中的某个数据并将该数据移出集合
spop key
eg:
127.0.0.1:6379> smembers myset
1) "7"
2) "5"
3) "2"
4) "9"
5) "6"
6) "3"
7) "world"
8) "4"
9) "1"
10) "hello"
11) "10"
12) "8"
127.0.0.1:6379> spop myset
"hello"
127.0.0.1:6379> spop myset
"3"
127.0.0.1:6379> smembers myset
1) "7"
2) "5"
3) "2"
4) "9"
5) "6"
6) "world"
7) "4"
8) "1"
9) "10"
10) "8"
两个集合的交、并、差集
sinter key1 [key2] # 交集
sunion key1 [key2] # 并集
sdiff key1 [key2] # 差集
eg:
127.0.0.1:6379> sadd key1 a b c
(integer) 3
127.0.0.1:6379> sadd key2 b c d
(integer) 3
127.0.0.1:6379> sinter key1 key2
1) "c"
2) "b"
127.0.0.1:6379> sunion key1 key2
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> sdiff key1 key2
1) "a"
两个集合的交、并、差集并存储到指定集合中
sinterstore destination key1 [key2]
sunionstore destination key1 [key2]
sdiffstore destination key1 [key2]
eg:
127.0.0.1:6379> sinterstore keystore1 key1 key2
(integer) 2
127.0.0.1:6379> smembers keystore1
1) "c"
2) "b"
127.0.0.1:6379> sunionstore keystore2 key1 key2
(integer) 4
127.0.0.1:6379> smembers keystore2
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> sdiffstore keystore3 key1 key2
(integer) 1
127.0.0.1:6379> smembers keystore3
1) "a"
127.0.0.1:6379> sdiffstore keystore4 key2 key1
(integer) 1
127.0.0.1:6379> smembers keystore4
1) "d"
将指定数据从原始集合中移动到目标集合中
smove source destination member
eg:
127.0.0.1:6379> smembers myset
1) "7"
2) "5"
3) "2"
4) "9"
5)"10"
127.0.0.1:6379> sadd myset1 1 2 3
(integer) 3
127.0.0.1:6379> smove myset myset2 10
(integer) 1
127.0.0.1:6379> smembers myset2
1) "10"
127.0.0.1:6379> smembers myset
1) "7"
2) "5"
3) "2"
4) "9"
注意事项
set 类型不允许数据重复,如果添加的数据在set 中已经存在,将只保留一份
set 虽然与hash 的存储结构相同,但是无法启用hash 中存储值得空间
应用场景
权限校验
解决方案:
- 依赖set集合数据不重复的特征,依赖set集合hash存储结构特征完成数据过滤与快速查询
- 根据用户id获取用户所有角色
- 根据用户所有角色获取用户所有操作权限放入set集合
- 根据用户所有角色获取用户所有数据全选放入set集合
黑白名单
解决方案:
- 基于经营战略设定问题用户发现、鉴别规则
- 周期性更新满足规则的用户黑名单,加入set集合
- 用户行为信息达到后与黑名单进行比对,确认行为去向
- 黑名单过滤设备信息:应用于限定访问设备的信息源
- 黑名单过滤用户:应用于基于访问权限的信息源
zset (sorted_set:有序集合)
新的存储需求:数据排序有利于数据的有效展示,需要提供一种可以根据自身特征进行排序的方式
需要的存储结构:新的存储模型,可以保存可排序的数据
zset 类型:在set的存储结构基础上添加可排序字段
基本操作
添加数据
zadd key score1 member1 [score2 member2]
eg:
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two 3 three
(integer) 2
获取全部数据
zrange key start stop [WITHSCORES]
zrevrange key start stop [WITHSCORES]
eg:
127.0.0.1:6379> zadd myclass 89 lili 67 bob 95 lucy 75 tom 59 frank 70 jack
(integer) 6
127.0.0.1:6379> zrange myclass 0 -1 # 从小到大排列
1) "frank"
2) "bob"
3) "jack"
4) "tom"
5) "lili"
6) "lucy"
127.0.0.1:6379> zrange myclass 0 -1 withscores # 从小到大排列(显示分数)
1) "frank"
2) "59"
3) "bob"
4) "67"
5) "jack"
6) "70"
7) "tom"
8) "75"
9) "lili"
10) "89"
11) "lucy"
12) "95"
127.0.0.1:6379> zrevrange myclass 0 -1 # 从大到小排列
1) "lucy"
2) "lili"
3) "tom"
4) "jack"
5) "bob"
6) "frank"
127.0.0.1:6379> zrevrange myclass 0 -1 withscores # 从大到小排列(显示分数)
1) "lucy"
2) "95"
3) "lili"
4) "89"
5) "tom"
6) "75"
7) "jack"
8) "70"
9) "bob"
10) "67"
11) "frank"
12) "59"
删除数据
zrem key member [member ...]
eg:
127.0.0.1:6379> zrem myclass frank
(integer) 1
按条件获取数据
zrangebyscore key min max [WITHSCORES] [LIMIT]
zrevrangebyscore key max min [WITHSCORES]
eg:
127.0.0.1:6379> zrangebyscore myclass 60 100
1) "bob"
2) "jack"
3) "tom"
4) "lili"
5) "lucy"
127.0.0.1:6379> zrangebyscore myclass 60 100 withscores
1) "bob"
2) "67"
3) "jack"
4) "70"
5) "tom"
6) "75"
7) "lili"
8) "89"
9) "lucy"
10) "95"
127.0.0.1:6379> zrevrangebyscore myclass 100 60
1) "lucy"
2) "lili"
3) "tom"
4) "jack"
5) "bob"
127.0.0.1:6379> zrevrangebyscore myclass 100 60 withscores
1) "lucy"
2) "95"
3) "lili"
4) "89"
5) "tom"
6) "75"
7) "jack"
8) "70"
9) "bob"
10) "67"
127.0.0.1:6379> zrangebyscore myclass -inf 60 withscores
1) "frank"
2) "59"
127.0.0.1:6379> zadd myclass 60 xiaoming
(integer) 1
127.0.0.1:6379> zrangebyscore myclass -inf 60 withscores
1) "frank"
2) "59"
3) "xiaoming"
4) "60"
条件删除数据
zremrangebyrank key start stop
zremrangebyscore key min max
eg:
127.0.0.1:6379> zremrangebyscore myclass 0 70
(integer) 3
127.0.0.1:6379> zrangebyscore myclass -inf +inf withscores
1) "tom"
2) "75"
3) "lili"
4) "89"
5) "lucy"
6) "95"
127.0.0.1:6379> zadd myclass 58 bob 68 xiaoming 72 jack
(integer) 3
127.0.0.1:6379> zrangebyscore myclass -inf +inf withscores
1) "bob"
2) "58"
3) "xiaoming"
4) "68"
5) "jack"
6) "72"
7) "tom"
8) "75"
9) "lili"
10) "89"
11) "lucy"
12) "95"
127.0.0.1:6379> zremrangebyrank myclass 0 1
(integer) 2
127.0.0.1:6379> zrangebyscore myclass -inf +inf withscores
1) "jack"
2) "72"
3) "tom"
4) "75"
5) "lili"
6) "89"
7) "lucy"
注意:
- min 与 max 用于限定搜索查询的条件
- start 与 stop 用于限定查询范围,作用于索引,表示开始和结束索引
- offset 与 count 用于限定查询范围,作用于查询结果,表示开始位置和数据总量
获取集合数据总量
zcard key
zcount key min max
eg:
127.0.0.1:6379> zrangebyscore myclass -inf +inf withscores
1) "jack"
2) "72"
3) "tom"
4) "75"
5) "lili"
6) "89"
7) "lucy"
8) "95"
127.0.0.1:6379> zcard myclass
(integer) 4
127.0.0.1:6379> zcount myclass 60 80
(integer) 2
127.0.0.1:6379> zcount myclass 80 100
(integer) 2
集合交、并操作
zinterstore destination numkeys key [key...]
zunionstore destination numkeys key [key...]
eg:
127.0.0.1:6379> zadd zset 60 one 65 two 78 three
(integer) 3
127.0.0.1:6379> zadd zset1 75 one 70 two 80 four
(integer) 3
127.0.0.1:6379> zinterstore outinter 2 zset zset1
(integer) 2
127.0.0.1:6379> zrange outinter 0 -1 withscores
1) "one"
2) "135"
3) "two"
4) "135"
127.0.0.1:6379> zunionstore outunion 2 zset zset1
(integer) 4
127.0.0.1:6379> zrange outunion 0 -1 withscores
1) "three"
2) "78"
3) "four"
4) "80"
5) "one"
6) "135"
7) "two"
8) "135"
127.0.0.1:6379> zadd zset2 80 one 85 two 68 three 90 four
(integer) 4
127.0.0.1:6379> zinterstore out 3 zset zset1 zset2
(integer) 2
127.0.0.1:6379> zrange out 0 -1 withscores
1) "one"
2) "215"
3) "two"
4) "220"
127.0.0.1:6379> zunionstore out1 3 zset zset1 zset2
(integer) 4
127.0.0.1:6379> zrange out1 0 -1 withscores
1) "three"
2) "146"
3) "four"
4) "170"
5) "one"
6) "215"
7) "two"
8) "220"
扩展操作
获取数据对应的索引(排名)
zrank key member
zrevrank key member
eg:
127.0.0.1:6379> zrank myclass jack
(integer) 0
127.0.0.1:6379> zrank myclass tom
(integer) 1
127.0.0.1:6379> zrevrank myclass lucy
(integer) 0
127.0.0.1:6379> zrevrank myclass tom
(integer) 2
score 值获取与修改
zscore key member
zincrby key increment member
eg:
127.0.0.1:6379> zscore myclass lucy
"95"
127.0.0.1:6379> zincrby myclass 3 lucy
"98"
127.0.0.1:6379> zscore myclass lucy
"98"
注意事项
- score 保存的数据存储空间是64位,如果是整数范围是 -9007199254740992 ~ 9007199254740992
- score 保存的数据也可以是一个双精度的double 值,基于双精度浮点数的特征,可能会丢失精度,使用时候要慎重
- zset 底层存储还是基于set 结构的,因此数据不能重复,如果重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果
应用场景
任务、消息权重设定应用
当任务或者消息待处理,形成了任务队列或消息队列时,对于高优先级的任务要保障对其优先处理,如何实现任务权重管理。
解决方案:
- 对于带有权重任务,优先处理权重高的任务,采用score记录权重即可。
- 多条件任务权重设定
如果权重条件过多时,需要排序score值进行处理,保障score值能够兼容2个条件或者多条件,例如外贸订单优先于国内订单,总裁订单优先于员工订单,经理订单优先于员工订单。 - 因score长度受限,需要对数据进行截断处理,尤其是时间设置为小时或分钟级即可
- 先设定订单类别,后设定订单发起角色类别,整体score长度必须是统一的,不足位补0。第一排序规则首位不得是0
例如外贸101,国内102,经理004,员工008
员工下的外贸订单score值为101008(优先)
经理下的国内订单score值为102004
geospatial (地理位置)
geoadd:将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。
- 有效的经度从-180度到180度。
- 有效的纬度从-85.05112878度到85.05112878度。
geo key longitude latitude member [longitude latitude member ...]
eg:
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou
(integer) 1
127.0.0.1:6379> geoadd china:city 113.24 23.12 guangzhou 114.08 22.547 shenzhen
(integer) 2
geopos:从key里返回所有给定位置元素的位置(经度和纬度)。
geopos key member [member ...]
eg:
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> geopos china:city shanghai
1) 1) "121.47000163793563843"
2) "31.22999903975783553"
127.0.0.1:6379> geopos china:city hangzhou shenzhen
1) 1) "120.1600000262260437"
2) "30.2400003229490224"
2) 1) "114.08000081777572632"
2) "22.54699993773966327"
geodist:返回两个给定位置之间的距离。
geodist key member1 member2 [unit]
指定单位的参数 unit 必须是以下单位的其中一个:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。
eg:
127.0.0.1:6379> geodist china:city beijing shanghai # 查看北京到上海的直线距离
"1067378.7564"
127.0.0.1:6379> geodist china:city beijing shanghai km
"1067.3788"
georadius: 以给定的经纬度为中心,找出某一半径内的元素
附近的人 获取所有附近的人的地址,定位,通过半径来查询
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
eg:
127.0.0.1:6379> georadius china:city 110 35 1000 km # 以经纬度110,35 为中心,查询1000km内的城市
1) "beijing"
127.0.0.1:6379> georadius china:city 110 30 1000 km
1) "shenzhen"
2) "guangzhou"
3) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist #显示到中心直线距离
1) 1) "shenzhen"
2) "923.2321"
2) 1) "guangzhou"
2) "830.2215"
3) 1) "hangzhou"
2) "977.5143"
127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord # 显示经纬度
1) 1) "shenzhen"
2) 1) "114.08000081777572632"
2) "22.54699993773966327"
2) 1) "guangzhou"
2) 1) "113.23999732732772827"
2) "23.1199990030198208"
3) 1) "hangzhou"
2) 1) "120.1600000262260437"
2) "30.2400003229490224"
127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord withdist count 1 # 显示指定的条数
1) 1) "guangzhou"
2) "830.2215"
3) 1) "113.23999732732772827"
2) "23.1199990030198208"
GEORADIUSBYMEMBER:找出位于指定范围内的元素,中心点是由给定的位置元素决定的。
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
eg:
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 1000 km # 找出指定元素 1000km 内的其他元素
1) "hangzhou"
2) "shanghai"
geohash:返回一个或多个位置元素的 [Geohash]
该命令将返回11个字符的Geohash字符串。
GEOHASH key member [member ...]
eg:
# 将二维的经纬度转换为一维的字符串
127.0.0.1:6379> geohash china:city beijing
1) "wx4fbxxfke0"
127.0.0.1:6379> geohash china:city beijing shanghai
1) "wx4fbxxfke0"
2) "wtw3sj5zbj0"
geo 底层的实现原理其实是 zset。我们可以使用zset 命令来操作 geo
127.0.0.1:6379> zrange china:city 0 -1
1) "shenzhen"
2) "guangzhou"
3) "hangzhou"
4) "shanghai"
5) "beijing"
127.0.0.1:6379> zrem china:city guangzhou
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "shenzhen"
2) "hangzhou"
3) "shanghai"
4) "beijing"
HyperLogLog
什么是基数
基数是指不重复的元素的个数。
A (1,3,5,7,8,7)
B (1,3,5,7,8)
# 基数:5
HyperLogLog 是一种用于计算唯一事物的概率数据结构。基数统计的算法。
优点:占用的内存是固定,2^64 不同的元素,只需 12kb 内存
0.81% 的错误率,统计uv 任务,可以忽略不计
网页的uv (一个人访问网站多次,还是算一个人)
传统的方式,set 保存用户的id,然后就可以统计set中元素数量作为标准判断!
这个方式保存大量的用户id,就会比较麻烦!我们的目的是为了计数,而不是保存用户id。
pfadd:将指定的元素添加到指定的key中
pfadd key element [element ...]
pfcount:查找指定key 不重复元素的个数
pfcount key [key ...]
pfmerge:合并目标的key 放入 destkey 中
pfmerge destkey sourcekey [sourcekey ...]
eg:
127.0.0.1:6379> pfadd logs 1 2 3 5 6 8 9 5 7 9
(integer) 1
127.0.0.1:6379> pfcount logs
(integer) 8
127.0.0.1:6379> pfadd mykey1 1 2 3 4 5 6 7 6 5
(integer) 1
127.0.0.1:6379> pfadd mykey2 2 5 7 9 10 11
(integer) 1
127.0.0.1:6379> pfmerge mykey3 mykey1 mykey2
OK
127.0.0.1:6379> pfcount mykey3
(integer) 10
Bitmaps (位存储)
Bitmaps 位图,数据结构,操作二进制位来进行记录,只有0 和 1 两个状态。
使用bitmaps 记录周一到周日的打卡
127.0.0.1:6379> setbit user:1 0 1 # 设置
(integer) 0
127.0.0.1:6379> setbit user:1 1 0
(integer) 0
127.0.0.1:6379> setbit user:1 2 1
(integer) 0
127.0.0.1:6379> setbit user:1 3 1
(integer) 0
127.0.0.1:6379> setbit user:1 4 0
(integer) 0
127.0.0.1:6379> setbit user:1 5 0
(integer) 0
127.0.0.1:6379> setbit user:1 6 0
(integer) 0
127.0.0.1:6379> getbit user:1 5 # 获取
(integer) 0
127.0.0.1:6379> bitcount user:1 # 统计数据
(integer) 3
网友评论