Redis 五大数据类型+三种特殊数据类型
Redis 五大数据类型
- String(字符串)
使用 append key名 增加的字符串,动态增加字符串(如果key不存在,就新建一个相当于set key value)
使用 strlen key名,查看字符串长度
使用 incr key名,增加key的数量
使用 decr key名,减少key的数量
使用 incrby key名 步长/decrby key名 步长,增加/减少key设置步长指定增量
使用 Getrange key名 0 3,截取下表为0~3的字符串(Getrange key名 0 -1==>查看全部字符串)
使用 setrange key名 1 "字符串1",用字符串1替换从1开始的字符串
使用 setex key名 秒数 "字符串1" ,set key名并设置多少秒过期
使用 setnx key名 "字符串1",set key名如果不存在才会设置,如果存在不会覆盖原来的key(分布式锁,乐观锁),就会创建失败
使用 mset key1 v1 key2 v2 key3 v3,同时设置多个key(msetnx :不存在就创建(原子性操作,如果有一个不成功,则所有都不成功))
使用 mget key1 key2 key3,同时取得多个key
使用 getset key名 "字符串1",如果存在值,则返回存在值,并设置新值,如果不存在,则返回null,设置新值(CAS)
(Redis事务是不保证原子性的)
对象
mget user:1:name user:1:age
mset user:1:name zhangsan user:1:age 3
mget user:1:name user:1:age
使用场景:value可以是字符串也可以是数字(计数器,文章阅读,统计多单位的数量,粉丝数(set uid:id:follow 0
))
- List
基本的数据类型,列表
在Redis可以把list当作栈,队列,阻塞队列
所有list命令都是以L开头
使用 lpush key名 值,将一个值或多个值插入列表的头部
使用 rpush key名 值,将一个值或多个值插入列表的尾部
lrange list 0 1/lrange list 0 -1 ,通过区间获取list的值
使用 lpop key名 数量,将一个值或多个值从表头移除
使用 rpop key名 数量,将一个值或多个值从表尾移除
使用 lindex key名 下标,通过下标获取值
使用 llen key名,得到list长度
使用 lrem key名 移除元素的个数 元素值,移除列表中指定的值
使用 ltrim key名 0 1,截取下标0到1的list(已经改变了list)
使用 rpoplpush 原列表 新列表,移除列表最后一个元素并添加到一个新的列表
使用 lset key名 下标 值,在key下标处设置值(更新操作)如果不存在列表会报错,如果存在就会更新
使用 linsert list before/after list中的某个值 插入值,在key中某个值的前面或后面插入新值
小结:
- 实际上是一个链表,before/after/left/right node
- 如果移除了所有值,列表也不存在了
- 在两边插入或者改动值,效率最高,在中间元素操作,相对来说会效率低一点
-
Set(集合)
Set 无序不重复集合
所有Set命令都是以s开头
使用 sadd key名 值,来增加set中的元素
使用 smembers key名,来获取set中的元素
使用 sismember key名 值,判断某个值是否在set中
使用 scard key名,获取set集合中的元素个数
使用 srem key名 值,移除set中的元素
使用 srandmember key名,随机获取一个set集合中的元素
使用 spop key名,随机删除一个set集合中的元素
使用 smove 源set 目的set 值,将源set的值移动到目标set中
使用 sdiff set1 set2,查找set1和set2的差集
使用 sinter set1 set2,查找set1和set2的交集
使用 sunion set1 set2,查找set1和set2的并集 -
Hash
Map集合,key-Map<key,value>
所有Hash命令都是以h开头
127.0.0.1:6379> hset myhash field1 Liuyunsan #set一个具体的key value
(integer) 1
127.0.0.1:6379> hget myhash field1 #get一个具体的key value
"Liuyunsan"
127.0.0.1:6379> hmset myhash field1 hello field2 world #set多个具体的key value
OK
127.0.0.1:6379> hget myhash field1
"hello"
127.0.0.1:6379> hget myhash field2
"world"
127.0.0.1:6379> hmget myhash field1 field2 #get多个具体的key value
1) "hello"
2) "world"
127.0.0.1:6379> hgetall myhash #获取全部的数据
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hdel myhash field1 #删除指定的key字段(对应的value也会消失)
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
127.0.0.1:6379>
127.0.0.1:6379> hlen myhash #获取hash表的字段数量
(integer) 1
127.0.0.1:6379> hexists myhash field2 #判断hash中的指定字段是否存在
(integer) 1
127.0.0.1:6379> hkeys myhash #获取hash表中的所有key
1) "field2"
127.0.0.1:6379> hvals myhash #获取hash表中的所有value
1) "world"
hincrby/hsetnx/hdecrby
存放变更的数据hset user:1 name Liuyunsan(用户信息之类,经常变动的信息)
hash适合对象存储
string适合字符串存储
- Zset(有序集合)
在set的基础上增加了一个值
set k1 v1
zset k1 score1 v1
127.0.0.1:6379> zadd myset 1 one #增加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three #增加多个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1 #显示所有值
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zadd salary 7000 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 70000 zzz
(integer) 1
127.0.0.1:6379> zadd salary 70 kkk
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf #从最小值到最大值排序
1) "kkk"
2) "xiaohong"
3) "zzz"
127.0.0.1:6379> zrevrange salary 0 -1 #从最大值到最小值排序
1) "zzz"
2) "xiaohong"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores #从最小值到最大值排序并附带成绩
1) "kkk"
2) "70"
3) "xiaohong"
4) "7000"
5) "zzz"
6) "70000"
127.0.0.1:6379> zrangebyscore salary -inf 7000
1) "kkk"
2) "xiaohong"
127.0.0.1:6379> zrem salary kkk #移除有序集合中的指定元素
(integer) 1
127.0.0.1:6379> zcard salary #获取集合中元素个数
(integer) 2
127.0.0.1:6379> zcount salary 0 7000 #获取指定区间中的元素个数
(integer) 1
127.0.0.1:6379> zcount salary 0 +inf
(integer) 2
总结:
set 排序版(班级成绩,工资表排序,普通消息设置为1,重要消息设置为2(加权重))
排行榜应用实现
Redis 三种特殊数据类型
- geospatial(地理位置)
Redis的Geo在Redis3.2版本就推出了,这个功能可以推算地理位置的信息(两地之间的距离,方圆几里的人)
命令 | 描述 |
---|---|
Redis GEOHASH 命令 | 返回一个或多个位置元素的 Geohash 表示 |
Redis GEOPOS 命令 | 从key里返回所有给定位置元素的位置(经度和纬度) |
Redis GEODIST 命令 | 返回两个给定位置之间的距离 |
Redis GEORADIUS 命令 | 以给定的经纬度为中心, 找出某一半径内的元素 |
Redis GEOADD 命令 | 将指定的地理空间位置(纬度、经度、名称)添加到指定的key中 |
Redis GEORADIUSBYMEMBER 命令 | 找出位于指定范围内的元素,中心点是由给定的位置元素决定 |
127.0.0.1:6379> geoadd china:city 39.90 116.40 beijing #将指定的地理空间位置(纬度、经度、名称)添加到指定的key中
(integer) 1
127.0.0.1:6379> geoadd china:city 31.23 121.47 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 29.53 160.50 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 22.52 114.05 shenzhen 22.55 113.88 futian
(integer) 2
127.0.0.1:6379> keys *
1) "china:city"
127.0.0.1:6379> geoadd china:city 30.24 121.16 hangzhou 34.26 108.96 xian
(integer) 2
127.0.0.1:6379> geopos china:city beijing #从key里返回所有给定位置元素的位置(经度和纬度
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> geopos china:city chongqing beijing
1) 1) "160.49999982118606567"
2) "29.52999957900659211"
2) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> geodist china:city beijing shanghai m #返回两个给定位置之间的距离
"1067378.7564"
127.0.0.1:6379> geodist china:city beijing shanghai km
"1067.3788"
127.0.0.1:6379> geodist china:city beijing shanghai ft
"3501898.8071"
127.0.0.1:6379> georadius china:city 110 30 1000 km #以给定的经纬度为中心, 找出某一半径内的元素
1) "xian"
2) "futian"
3) "shenzhen"
127.0.0.1:6379> georadius china:city 110 30 500 km
1) "xian"
127.0.0.1:6379> georadius china:city 110 30 5000 km withdist withcoord count 1
1) 1) "xian"
2) "483.8340"
3) 1) "108.96000176668167114"
2) "34.25999964418929977"
127.0.0.1:6379> georadiusbymember china:city beijing 1000 km #找出位于指定范围内的元素,中心点是由给定的位置元素决定
1) "beijing"
2) "xian"
127.0.0.1:6379> geohash china:city beijing #返回一个或多个位置元素的 Geohash 表示(将二维的经纬度转换为一维的字符串(字符串越接近距离越近))
1) "wx4fbxxfke0"
南北两极无法添加,一般会下载城市数据,通过java程序导入
geoadd key名 精度 纬度 名称
有效的经度从-180度到180度。
有效的纬度从-85.05112878度到85.05112878度。
(附近的人)==>获得所有附近的人的地址(定位),通过半径来查询
GEO底层的实现原理:Zset,我们可以使用Zset命令来操作geo
127.0.0.1:6379> zrange china:city 0 -1 #查看全部元素
1) "xian"
2) "futian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
7) "chongqing"
127.0.0.1:6379> zrem china:city xian #移除指定元素
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "futian"
2) "shenzhen"
3) "hangzhou"
4) "shanghai"
5) "beijing"
6) "chongqing"
- hyperloglog(一种数据结构)
基数统计算法
什么是基数?==>重复的元素个数
A{1,3,5,7,8,9}
B{1,3,5,7,8}
优点:占用内存固定,2^64不同的元素的数据,只需12kb的内存,如果要从内存角度来比较的话。Hyperloglog的首选
缺点:0.81%的错误率
网页的页面访问量(一个人访问多次还是算一个人)
传统方式:set保存用户的id(不允许重复),然后统计数量作为判断标准==>保存大量的用户id比较占用内存但是没有错误率
hyperloglog:
127.0.0.1:6379> pfadd mykey a b c d e f g h i j #创建第一组元素
(integer) 1
127.0.0.1:6379> pfcount mykey #统计第一组元素数量
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c b m #创建第二组元素
(integer) 1
127.0.0.1:6379> pfcount mykey2 #统计第二组元素数量
(integer) 7
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 #合并两组(并集)
OK
127.0.0.1:6379> pfcount mykey3
(integer) 13
- bitmaps (位存储)(存储只有两个状态的信息)
统计活跃用户信息: 1 1 1 1 1 1 1 0 0 0
统计打卡信息: 1 0 0 1 0 1 0 1 0 1 0
位图,数据结构,都是二进制位进行记录,就只有0和1两个状态==>节省内存
127.0.0.1:6379> setbit sign 0 0 #是用bitmap记录周一到周日的打卡
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 6 1
(integer) 0
127.0.0.1:6379> getbit sign 3 #查看某一天是否有打卡
(integer) 0
127.0.0.1:6379> getbit sign 4
(integer) 1
127.0.0.1:6379> bitcount sign #统计打卡天数
(integer) 3