Redis学习笔记3:五大数据类型(StringListSetHashZset)和三种特殊数据类型(geospatialHyperloglogBitmaps)
Posted Vincent9847
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis学习笔记3:五大数据类型(StringListSetHashZset)和三种特殊数据类型(geospatialHyperloglogBitmaps)相关的知识,希望对你有一定的参考价值。
介绍:
Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ,它支持多种类型的数据结构,如字符串( strings ) ,散列(hashes ) ,列表( lists ) ,集合(sets ) ,有序集合(sorted sets)与范围查询,bitmaps, hyperloglogs和地理空间( geospatial )索引半径查询. Redis内置了复制( replication ) , LUA脚本(Lua scripting ) , LRU驱动事件( LRU eviction ) ,事务(transactions )和不同级别的磁盘持久化( persistence ) ,并通过Redis哨兵(Sentinel )和自动分区( Cluster )提供高可用性(high availability ).
基础命令:
127.0.0.1:6379> ping #测试链接
PONG #连接成功
一、五大数据类型
1.String
介绍:
String 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字。
常用命令:get、set、incr、decr、mget等。
使用场景:常规key-value缓存应用。常规计数: 微博数, 粉丝数。
实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
1.设置字符串、判断是否存在、追加字符串、字符串长度、截取、替换
127.0.0.1:6379> set key1 v1 #设置值
OK
127.0.0.1:6379> get key1 #获得值
"v1"
127.0.0.1:6379> keys * 获得所有的key
1) "key1"
127.0.0.1:6379> exists key1 #判断是否存在key1
(integer) 1
127.0.0.1:6379> append key1 hello #追加字符串,如果key不存在,就相当于setkey
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1 #获取字符串长度
(integer) 7
127.0.0.1:6379> getrange key1 0 3 #截取字符串
"v1he"
127.0.0.1:6379> getrange key1 0 -1 #查看字符串
"v1hello"
127.0.0.1:6379> setrange key1 1 xx #字符串替换
(integer) 7
127.0.0.1:6379> get key1
"vxxello"
2.设置过期时间setex、setnx
#setex (set with expire) #设置过期时间
#setnx (set if not exist) #不存在再设置(在分布式锁中会常常使用! )
127.0.0.1:6379> setex key3 30 "hel1o" #设置key3的值为hel1o, 30秒后过期
оK
127.0.0.1:6379> ttl key3
(integer) 26
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> setnx mykey "redis" #如果mykey不存在,创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "key2"
2) "mykey"
3) "keyl"
127.0.0.1:6379> tt1 key3
(integer) -2
127.0.0.1:6379> setnx mykey "MongoDB" #如果mykey存在,创建失败!
(integer) 0
127.0.0.1:6379> get mykey
"redis"
3.同时设置多个值
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k1"
2) "K2"
3) "k3"
127.0.0.1:6379> mget k1 k2 k3 # 同时获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4 #msetnx是一个原子性的操作,要么一起成功,要么一起失败!
(integer) 0
127.0.0.1:6379> get k4
(nil)
4.设置对象值
#对象
set user:1 name:zhangsan, age:3 #设置一个user:1对象 值为json字符来保存一个对象!
#这里的key是一个巧妙的设计: user:[id :filed ,如此设计在Redis中是完全0K了!
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
ОK
127.0.0.1:6379> mget user:1:name user:1: age
1) "zhangsan"
2)"2"
5.getset 组合命令
getset#先get然后再set
127.0.0.1:6379> getset key redis #如果不存在值,则返回nil
(nil)
127.0.0.1:6379> get key
"redis"
127.0.0.1:6379> getset key mongodb #如果存在值,获取原来的值,并设置新的值
"redis"
127.0.0.1:6379> get key
"mongodb"
6.计数(阅读量)
127.0.0.1:6379> set num1 20
OK
127.0.0.1:6379> type num1
string
127.0.0.1:6379> incr num1 #增加1
(integer) 21
127.0.0.1:6379> decr num1 #减少1
(integer) 20
127.0.0.1:6379> incrby num1 10 #指定步长增量
(integer) 30
127.0.0.1:6379> decrby num1 10 #指定步长减量
(integer) 20
2.List(列表)
介绍:
常用命令:lpush,rpush,lpop,rpop,lrange等。
应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。
List 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用List结构,我们可以轻松地实现最新消息排行等功能。List的另一个应用就是消息队列,
可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
Redis的list是每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部添加或者删除元素,这样List即可以作为栈,也可以作为队列。
1.设置获取值
127.0.0.1:6379> lpush list one #将一个值或者多个值,插入到列表头部(左)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1 #获取1ist中值!
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1 #通过区间获取具体的值!
1) "three"
2) "two"
127.0.0.1:6379> rpush list righr #将一个值或者多个值,插入到列表位部(右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "righr"
2.移除 lpop、rpop
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "righr"
127.0.0.1:6379> lpop list #移除list的第一个元素
"three"
127.0.0.1:6379> rpop list #移除list的最后一个元素
"righr"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3.list 长度、获取下标值、截取list、移除指定值
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "four"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379> llen list #获取列表长度
(integer) 5
127.0.0.1:6379> lindex list 1 #根据下获取值
"four"
127.0.0.1:6379> ltrim list 1 2 #截取list下标1到下标2
OK
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "three"
127.0.0.1:6379> lrem list 1 four #移除一个four
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
4.rpoplpush移除、更新下标元素值、插入元素
127.0.0.1:6379> rpush list one
(integer) 1
127.0.0.1:6379> rpush list two
(integer) 2
127.0.0.1:6379> rpush list three
(integer) 3
127.0.0.1:6379> rpoplpush list list1 #移除list列表最后一个元素到list1列表
"three"
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "two"
127.0.0.1:6379> lrange list1 0 -1
1) "three"
127.0.0.1:6379> lset list 0 one1 #更新下标为0的元素值
OK
127.0.0.1:6379> lrange list 0 -1
1) "one1"
2) "two"
127.0.0.1:6379> linsert list before two one2 #在元素two之前插入元素one2(之后为after)
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "one1"
2) "one2"
3) "two"
3.Set(集合)
介绍:
常用命令:sadd,spop,smembers,sunion 等。
应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Set 就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的Set数据结构,可以存储一些集合性的数据。
案例:在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。
Set是集合,是String类型的无序集合,set是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等,set中的元素是没有顺序的。
实现方式: set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。
1.添加、查看、存在
127.0.0.1:6379> sadd myset hello #set集合添加值
(integer) 1
127.0.0.1:6379> sadd myset xiaoyi
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> smembers myset #查看所有值
1) "xiaoyi"
2) "hello"
3) "world"
127.0.0.1:6379> sismember myset hello 判断是否存在值
(integer) 1
127.0.0.1:6379> sismember myset you
(integer) 0
2.获取、移除、随机显示、随即删除
127.0.0.1:6379> scard myset #获取集合元素个数
(integer) 3
127.0.0.1:6379> srem myset hello #移除hello元素
(integer) 1
127.0.0.1:6379> smembers myset
1) "xiaoyi"
2) "world"
127.0.0.1:6379> srandmember myset 1 #随机显示一个元素
1) "world"
127.0.0.1:6379> srandmember myset 2 #随机显示两个元素
1) "xiaoyi"
2) "world"
127.0.0.1:6379> spop myset #随机删除元素
"world"
127.0.0.1:6379> smembers myset
1) "xiaoyi"
3.差集、交集、并集
127.0.0.1:6379> sadd key1 a b c
(integer) 3
127.0.0.1:6379> sadd key2 c d e
(integer) 3
127.0.0.1:6379> sdiff key1 key2 #查看两个集合的差集【a,b】
1) "a"
2) "b"
127.0.0.1:6379> sinter key1 key2 #交集 【c】
1) "c"
127.0.0.1:6379> sunion key1 key2 #并集 【a,b,c,d,e】
1) "b"
2) "a"
3) "e"
4) "c"
5) "d"
4.Hash(哈希)
介绍:
使用场景:存储部分变更数据,如用户信息等。
实现方式:上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
1.设置值、设置多值、删除字段、存在、
127.0.0.1:6379> hset myhash field v1 #设置值
(integer) 1
127.0.0.1:6379> hget myhash field
"v1"
127.0.0.1:6379> hmset myhash field1 v1 field2 v2 #设多值
OK
127.0.0.1:6379> hmget myhash field1 field2 #获取多个字段值
1) "v1"
2) "v2"
127.0.0.1:6379> hgetall myhash #获取全部数据
1) "field"
2) "v1"
3) "field1"
4) "v1"
5) "field2"
6) "v2"
127.0.0.1:6379> hdel myhash field #删除指定的字段
(integer) 1
127.0.0.1:6379> hlen myhash #获取字段数量
(integer) 2
127.0.0.1:6379> hexists myhash field1 #判断指定字段是否存在
(integer) 1
127.0.0.1:6379> hkeys myhash #获取所有字段
1) "field1"
2) "field2"
127.0.0.1:6379> hvals myhash #获取所有值
1) "v1"
2) "v2"
2.增量、存在设值
127.0.0.1:6379> hset myhash field3 5 #设置值
(integer) 1
127.0.0.1:6379> hincrby myhash field3 1 #指定增量
(integer) 6
127.0.0.1:6379> hincrby myhash field3 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash field4 hello #如果不存在则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world #如果存在则不能设置
(integer) 0
127.0.0.1:6379>
5.Zset(有序集合)
介绍:
常用命令:zadd,zrange,zrem,zcard等
使用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
和Set相比,Sorted Set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列,比如一个存储全班同学成绩的Sorted Set,其集合value可以是同学的学号,而score就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。另外还可以用Sorted Set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。
实现方式: Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
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> zrangebyscore myset -inf +inf #显示全部,从小到大
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zrangebyscore myset -inf +inf withscores #显示全部,从小到大,且附带值
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379> zrangebyscore myset -inf 2 withscores #显示小于等于2的数据
1) "one"
2) "1"
3) "two"
4) "2"
127.0.0.1:6379> zrange myset 0 -1 #查看全部元素
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zrem myset two #移除指定元素
(integer) 1
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "three"
127.0.0.1:6379> zcard myset #获取游戏集合中的个数
(integer) 2
127.0.0.1:6379> zcount myset 1 1 #获取指定区间成员数量
(integer) 1
127.0.0.1:6379> zcount myset 3 3
(integer) 1
127.0.0.1:6379> zcount myset 1 3
(integer) 2
二、3种特殊数据类型
1.geospatial (地理位置)
介绍:
这个功能可以将用户给定的地理位置信息储存起来, 并对这些信息进行操作
geo 的数据结构总共有六个命令
- geoadd
- geopos
- geodist
- georadius
- georadiusbymember
- geohash
#getadd添加地理位置
#规则:两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入!
#有效的经度从-180度到180度。
#有效的纬度从-85.05112878度到85.05112878度。
#当坐标位置超出上述指定范围时,该命令将会返回一个错误。
#127.0.0.1:6379> geoadd china:city 39.90 116.40 beijin
#(error) ERR invalid longitude, latitude pair 39.900000,116.400000
1.参数key 值()
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 106.50 29.53 chongqi 114.05 22.52 shengzhen #多值
(integer) 2
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian
(integer) 2
127.0.0.1:6379> geopos china:city beijing #获取指定城市经纬度
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> geodist china:city beijing shanghai #获取两个城市直线距离
"1067378.7564"
127.0.0.1:6379> georadius china:city 110 30 1000 km #获取指定坐标方圆1000km内的城市
1) "chongqi"
2) "xian"
3) "shengzhen"
4) "hangzhou"
#获取beijing方圆1000km内的城市
127.0.0.1:6379> georadiusbymember china:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> geohash china:city beijing shanghai #将坐标转为字符串
1) "wx4fbxxfke0"
2) "wtw3sj5zbj0"
127.0.0.1:6379> zrange china:city 0 -1 #查看所有数据
1) "chongqi"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city beijing #移除指定数据
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqi"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "shanghai"
2.附带值 withdist直线距离、withcoord其他坐标、count 2显示数量
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist #附带之间距离
1) 1) "chongqi"
2) "341.9374"
2) 1) "xian"
2) "483.8340"
3) 1) "shengzhen"
2) "924.6408"
4) 1) "hangzhou"
2) "977.5143"
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist withcoord#附带其他城市坐标
1) 1) "chongqi"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) "483.8340"
3) 1) "108.96000176668167114"
2) "34.25999964418929977"
3) 1) "shengzhen"
2) "924.6408"
3) 1) "114.04999762773513794"
2) "22.5200000879503861"
4) 1) "hangzhou"
2) "977.5143"
3) 1) "120.1600000262260437"
2) "30.2400003229490224"
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist withcoord count 2#显示数量
1) 1) "chongqi"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) "483.8340"
3) 1) "108.96000176668167114"
2) "34.25999964418929977"
2.Hyperloglog
介绍:
Hyperloglog基数统计的算法。不过会有些许误差,如果允许容错,使用Hyperloglog,不允许容错的话使用set
基数=不重复元素的个数
127.0.0.1:6379> PFadd mykey a b c e f g h i j #创建第一组元素mykey
(integer) 1
127.0.0.1:6379> PFCOUNT mykey #统计mykey元素的基数数量
(integer) 10
127.0.0.1:6379> PFadd mykey2 i j k l m n #创建第二组元素mykey2
(integer) 1
127.0.0.1:6379> PFCOUNT mykey2
(integer) 9
127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 #合并两组mykey mykey2 => mykey3并集
OK
127.0.0.1:6379> PFCOUNT mykey3 #看并集的数量!
(integer) 15
3.Bitmaps(位图)
介绍:
Bitmap就是通过一个
bit
位来表示某个元素对应的值或者状态。Bitmaps位图,只有0和1两个状态。位存储。可以用来统计用户信息,登陆,未登录;打卡。
127.0.0.1:6379> setbit key 0 1
(integer) 0
127.0.0.1:6379> setbit key 1 0
(integer) 0
127.0.0.1:6379> setbit key 2 0
(integer) 0
127.0.0.1:6379> setbit key 3 1
(integer) 0
127.0.0.1:6379> setbit key 4 1
(integer) 0
127.0.0.1:6379> setbit key 5 0
(integer) 0
127.0.0.1:6379> getbit key 2 #查看下标为2的位
(integer) 0
127.0.0.1:6379> getbit key 3
(integer) 1
127.0.0.1:6379> bitcount key #计数为1的
(integer) 3
以上是关于Redis学习笔记3:五大数据类型(StringListSetHashZset)和三种特殊数据类型(geospatialHyperloglogBitmaps)的主要内容,如果未能解决你的问题,请参考以下文章