Redis五大数据类型(二)
二、五大数据类型
Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。
它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。
内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,
同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
String(字符串)
追加
append key value 向指定的key的value后追加字符串
127.0.0.1:6379> set msg hello
OK
127.0.0.1:6379> append msg " world"
(integer) 11
127.0.0.1:6379> get msg
“hello world”
增加减少
decr/incr key 将指定key的value数值进行+1/-1(仅对于数字)
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> incr age
(integer) 21
127.0.0.1:6379> decr age
(integer) 20
incrby/decrby key n 按指定的步长对数值进行加减
127.0.0.1:6379> set age 20
127.0.0.1:6379> INCRBY age 5
(integer) 25
127.0.0.1:6379> DECRBY age 10
(integer) 15
INCRBYFLOAT key n 为数值加上浮点型数值
127.0.0.1:6379> INCRBYFLOAT age 5.2
“20.2”
字符串范围(闭区间)
strlen key 获取key保存值的字符串长度 127.0.0.1:6379> get msg “hello world” 127.0.0.1:6379> STRLEN msg (integer) 11
getrange key start end 按起止位置获取字符串(闭区间,起止位置都取)
127.0.0.1:6379> set name hhello
127.0.0.1:6379> getrange name 0 -1
"hhello"
替换指定位置字符串
setrange key offset value 用指定的value 替换key中 offset开始的值(包含offset)
127.0.0.1:6379> get name
"helloo"
127.0.0.1:6379> setrange name 1 xxx
(integer) 6
127.0.0.1:6379> get name
"hxxxoo"
127.0.0.1:6379>
*分布式锁中常用(set with expire与set if no exist)
setex key seconds value set 键值对 并 设置过期时间
设置name--“jack”且30秒后删除
127.0.0.1:6379> setex name 30 "jack"
OK
127.0.0.1:6379> get name
"jack"
127.0.0.1:6379> ttl name
(integer) 13
127.0.0.1:6379> get name
(nil)
setnx key value 仅当key不存在时进行set
127.0.0.1:6379> setnx name "11"
(integer) 1
127.0.0.1:6379> get name
"11"
127.0.0.1:6379> setnx name "dd"
(integer) 0
批量设置mset、mget
mset key1 value1 [key2 value2..] 批量set键值对
127.0.0.1:6379> MSET k1 v1 k2 v2 k3 v3
mget key1 value1 [key2 value2..] 批量获取多个key保存的值
127.0.0.1:6379> MGET k1 k2 k3
msetnx是一个原子性的操作,要么都成功,要么都失败
msetnx key1 value1 [key2 value2..] 批量设置键值对,仅当参数中所有的key都不存在时执行
127.0.0.1:6379> MSETNX k1 v1 k4 v4
(integer) 0
对象
127.0.0.1:6379> mset user:1:name jack user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
- "jack"
- "2"
组合命令getset
getset key value 先get再set
如果不存在,返回nil;如果存在,将给定 key 的值设为 value ,并返回 key 的旧值(old value)
127.0.0.1:6379> getset db redis
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mysql
"redis"
127.0.0.1:6379> get db
"mysql"
总结:String类似的使用场景
value除了是字符串还可以是数字,用途举例:
-
计数器、粉丝数、对象存储缓存
-
统计多单位的数量:uid:123666:follow 0
List(列表)
list列表,可以经过规则定义将其变为队列、栈、双端队列等。所有的list命令都是L
开头
lpush/rpush key value1[value2..] 从左边/右边向列表中PUSH值(一个或者多个)。
lrange key start end 获取list 起止元素(索引从左往右 递增)
127.0.0.1:6379> lpush list a
(integer) 1
127.0.0.1:6379> lpush list b
(integer) 2
127.0.0.1:6379> rpush list c
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "b" 2) "a" 3) "c"
lpop/rpop key 从最左边/最右边移除值 并返回
lindex key index 通过索引获取列表元素
Llen key 查看列表长度
Lrem key count value 移除指定的值,cout表示移除的个数,可省略
List中是允许value重复的
count > 0:从头部开始搜索 然后删除指定的value 至多删除count个
count < 0:从尾部开始搜索…
count = 0:删除列表中所有的指定value。
127.0.0.1:6379> lrange list 0 -1
1) "a"
2) "c"
127.0.0.1:6379> lrem list 1 a
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "c"
ltrim key start stop 修剪,截头截尾(key的下标从0开始,闭区间)
127.0.0.1:6379> lrange list 0 -1
"a" "b" "c" "d" "e"
127.0.0.1:6379> ltrim list 1 3
OK
127.0.0.1:6379> lrange list 0 -1
"b" "c" "d"
rpoplpush source destination 将列表的尾部(右)最后一个值弹出,并返回,然后添加到另一个列表的头部
127.0.0.1:6379> lrange list 0 -1
"b" "c" "d"
127.0.0.1:6379> rpoplpush list newlist
"d"
127.0.0.1:6379> lrange list 0 -1
"b" "c"
127.0.0.1:6379> lrange newlist 0 -1
"d"
lset key index value 通过索引为元素设值
127.0.0.1:6379> lrange list 0 -1
1) "old"
127.0.0.1:6379> lset list 0 new
OK
127.0.0.1:6379> lrange list 0 -1
1) "new"
linsert key BEFORE|AFTER pivot value 在指定列表元素的前/后 插入value
127.0.0.1:6379> lrange list 0 -1
"a"
127.0.0.1:6379> linsert list before "a" "z"
127.0.0.1:6379> linsert list after "a" "b"
127.0.0.1:6379> lrange list 0 -1
"z" "a" "b"
总结
list实际是一个链表,before, after , left, right 都可以插入值
如果移除了所有值,空链表,也代表不存在
在两边插入或者改动值,效率最高!修改中间元素,效率相对较低
应用:消息排队!消息队列(Lpush Rpop),栈(Lpush Lpop)
Set(无序集合)
Redis的Set是string类型的无序集合。集合成员是唯一的,
这就意味着集合中不能出现重复的数据。
Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
命令
sadd key member1[member2..] 向集合中无序增加一个/多个成员
smembers key 返回集合中所有的成员
sismember key member1 查询member1元素是否是集合的成员,结果是无序的
scard key 获取集合的成员数
srem key member1[member2..] 移除集合中一个/多个成员
srandmember key [count] 随机返回集合中count个成员,count缺省值为1
spop key [count] 随机移除并返回集合中count个成员,count缺省值为1
smove source destination member 将source集合的成员member移动到destination集合
sdiff key1 [key2..] 返回所有集合的差集 key1- key2 - …
sinter key1 [key2..] 返回所有集合的交集
sunion key1 [key2..] 返回所有集合的并集
sdiffstore destination key1[key2..] 在SDIFF的基础上,将结果保存到集合中(覆盖)。不能保存到其他类型key噢!
sinterstore destination key1[key2..] 在SINTER的基础上,存储结果到集合中。覆盖
sunionstore destination key1 [key2..] 在SUNION的基础上,存储结果到集合中。覆盖
sscan key [MATCH pattern] [COUNT count] 在大量数据环境下,使用此命令遍历集合中元素,每次遍历部分??????
Hash(哈希)
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
Set就是一种简化的Hash,只变动key,而value使用默认值填充。可以将一个Hash表作为一个对象进行存储,表中存放对象的信息。
命令
hset key field value 将哈希表 key 中的字段 field 的值设为 value 。重复设置同一个field会覆盖,返回0
hmset key field1 value1 [field2 value2..] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
hget key field value 获取存储在哈希表中指定字段的值
hmget key field1 [field2..] 获取所有给定字段的值
hgetall key 获取在哈希表key 的所有字段和值
127.0.0.1:6379> hset myhash field1 "a"
(integer) 1
127.0.0.1:6379> hget myhash field1
"a"
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "a"
hdel key field1 [field2..] 删除哈希表key中一个/多个field字段
hsetnx key field value 只有在字段 field 不存在时,设置哈希表字段的值。
hexists key field 查看哈希表 key 中,指定的字段是否存在。
hlen key 获取哈希表中字段的数量
hkeys key 获取哈希表key中所有的字段
hvals key 获取哈希表中所有值
hincrby key field n 为哈希表 key 中的指定字段的整数值加上增量n,并返回增量后结果 一样只适用于整数型字段
HSCAN key cursor [MATCH pattern] [COUNT count] 迭代哈希表中的键值对。
总结
Hash变更的数据user name age,尤其是用户信息之类的,经常变动的信息!Hash更适合于对象的存储,Sring更加适合字符串存储!
Zset(有序集合)
sadd sset one
对比zadd sset 1 one
,与set相比多了一个score
不同的是每个元素都会关联一个(double类型的) score
redis正是通过分数来为集合中的成员进行从小到大的排序。
score相同:按字典顺序排序
有序集合的成员是唯一的,但score却可以重复。
序集合的成员是唯一的,但分数(score)却可以重复。
命令
zadd key score member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
zrange key start end 通过索引区间返回有序集合成指定区间内的成员
zrevrange key start end 返回有序集中指定区间内的成员,通过索引,分数从高到底
127.0.0.1:6379> zadd sset 1 one
(integer) 1
127.0.0.1:6379> zadd sset 3 three 2 two
(integer) 2
127.0.0.1:6379> zrange sset 0 -1
1) "one"
2) "two"
3) "three"
zrem key member1 [member2..] 移除有序集合中一个/多个成员
zcard key 获取有序集合的成员数
zcount key min max 计算在有序集合中指定区间score的成员数
zincrby key n member 有序集合中对指定成员的分数加上增量 n
zscore key member 返回有序集中,成员的分数值
zrank key member 返回有序集合中指定成员的索引
zrangebylex key min max 通过字典区间返回有序集合的成员
zrangebyscore key min max 通过分数返回有序集合指定区间内的成员,其中-inf 和 +inf分别表示最小最大值,只支持开区间()
应用案例
set排序、 存储班级成绩表、 工资表排序!
带权重进行判断:普通消息--1. 重要消息--2.
排行榜应用实现,取Top N测试
三、三种特殊数据类型
1 Geospatial(地理位置)
使用经纬度定位地理坐标并用一个有序集合zset保存,所以zset命令也可以使用
geoadd key longitud(经度) latitude(纬度) member(城市名) [..] 将具体经纬度的坐标存入一个有序集合
geopos key member [member..] 获取集合中的一个/多个成员坐标
geopos china:city beijing
geodist key member1 member2 [unit] 返回两个给定位置之间的距离。默认以米作为单位。
(unit:m 表示单位为米。 km 表示单位为千米)
查看北京到上海的直线距离:geodist china:city beijing shanghai km
georadius key longitude latitude radius km [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
以给定的经纬度为中心, 找出某一半径内的元素
radius:半径;withcoord:带上坐标;withdist:带上距离,单位与半径单位相同;COUNT n:只显示前n个(按距离递增排序)
georadiusbymember key member radius... 功能与georadius相同,只是中心位置不是具体的经纬度,而是使用结合中已有的成员作为中心点
geohash key member1 [member2..] 返回一个或多个位置元素的Geohash表示。使用Geohash位置52点整数编码。
移除元素:由于geo底层是zset,可以使用:
zrem china:city beijing
2 Hyperloglog(基数统计)
简介
Redis HyperLogLog 是用来做基数(数据集中不重复的元素的个数)统计的算法,
HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。其底层使用string数据类型
应用场景
网页的访问量(UV):一个用户多次访问,也只能算作一个人。
传统实现:存储用户的id,然后每次进行比较。当用户变多之后这种方式及其浪费空间,而我们的目的只是计数,Hyperloglog就能帮助我们利用最小的空间完成。
如果允许容错,那么一定可以使用Hyperloglog !
如果不允许容错,就使用set或者自己的数据类型即可 !
命令
PFadd key element1 [elememt2..] 添加指定元素到 HyperLogLog 中
PFcount key [key] 返回给定 HyperLogLog 的基数估算值。
PFmerge destkey sourcekey [sourcekey..] 将多个 HyperLogLog 合并为一个 HyperLogLog
合并myelemx和myelemy 成为myelemz :PFmerge myelemz myelemx myelemy
127.0.0.1:6379> pfadd key a b c d e
(integer) 1
127.0.0.1:6379> pfadd key1 a b c r g g
(integer) 1
127.0.0.1:6379> pfmerge key2 key key1
OK
127.0.0.1:6379> pfcount key2
(integer) 7 #合并后只有7个了 ,abcde+rg
3 BitMaps(位图)
使用位存储,信息状态只有 0 和 1
Bitmap是一串连续的2进制数字(0或1),每一位所在的位置为偏移(offset),在bitmap上可执行AND,OR,XOR,NOT以及其它位操作。
应用场景:签到统计、状态统计
setbit、getbit、bitcount
bitcount key [start end]
统计字符串被设置为1的bit数,也可以指定统计范围按字节
------------setbit--getbit--------------
127.0.0.1:6379> setbit sign 0 1 # 设置sign的第0位为 1
(integer) 0
127.0.0.1:6379> setbit sign 2 1 # 设置sign的第2位为 1 不设置默认 是0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
127.0.0.1:6379> getbit sign 2 # 获取第2位的数值
(integer) 1
-----------bitcount----------------------------
127.0.0.1:6379> bitcount sign # 统计sign中为1的位数
(integer) 2
https://www.bilibili.com/video/BV1S54y1R7SB?from=search&seid=3929831479981400108