Redis各种数据类型

2022-03-23 20:13:10 浏览数 (1)

Redis五大数据类型

Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。

本文章简单介绍各种类型的基础用法 本文章参考了狂神的视频此处

Redis-Key

代码语言:javascript复制
exists   key  判断是否存在key

move key  移除key

expire key  10  设置10秒后key过期

ttl key  查看key剩余过期时间

type key  查看key的类型
代码语言:javascript复制
  命令                	描述                                      
  Redis Type 命令     	返回 key 所储存的值的类型。                        
  Redis PEXPIREAT 命令	设置 key 的过期时间亿以毫秒计。                      
  Redis PEXPIREAT 命令	设置 key 过期时间的时间戳(unix timestamp) 以毫秒计    
  Redis Rename 命令   	修改 key 的名称                              
  Redis PERSIST 命令  	移除 key 的过期时间,key 将持久保持。                 
  Redis Move 命令     	将当前数据库的 key 移动到给定的数据库 db 当中。            
  Redis RANDOMKEY 命令	从当前数据库中随机返回一个 key 。                     
  Redis Dump 命令     	序列化给定 key ,并返回被序列化的值。                   
  Redis TTL 命令      	以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
  Redis Expire 命令   	seconds 为给定 key 设置过期时间。                 
  Redis DEL 命令      	该命令用于在 key 存在是删除 key。                   
  Redis Pttl 命令     	以毫秒为单位返回 key 的剩余的过期时间。                  
  Redis Renamenx 命令 	仅当 newkey 不存在时,将 key 改名为 newkey 。       
  Redis EXISTS 命令   	检查给定 key 是否存在。                          
  Redis Expireat 命令 	EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
  Redis Keys 命令     	查找所有符合给定模式( pattern)的 key 。         

String(字符串)

代码语言:javascript复制
set k1  v1   设置一个 key为 k1 值为 v1 
get k1   
APPEND k1 "hello"  向k1中追加一个字符串hello  如果当前key不存在就相当于set key
get k1         取出来"v1hello"
STRLEN k1   获取字符串长度 

incr key      key值    自增1
decr key      key值--  自减1
incrby key  10  key值 10 
decrby key  5   key值-5

字符串范围
getrange key 0 2   获取key的value中 前三个字符[0,2]
getrange key 0 -1  获取key中所有的字符   和get key是一样的
替换
setrange key 2 h  把key值的第三个字符开始的字符串替换成 h



setex(set with expire)  设置过期时间
setex key 30 "hello"    写一个key 值为 hello 字符串过期时间为30秒

setnx (set with not expire)  如果当前值不存在我们创建
setnx key "hh"
设置成功返回1  设置不成功返回0  在分布式锁中经常使用



批量设置值
mset  批量设置多个值   空格分割
mset k1 v1 k2 v2 k3 v3
mget   获取多个值
mget k1 k2 k3 
msetnx  如果不存在我们创建   如果  设置多对值其中一对值存在则添加失败(原子性操作)
mestnx k1 v1 k4 v4   k1存在创建失败

#存储对象
set user:1 {name:zhangsan,age:23} 设置一个user:1对象 值为json字符串来保存一个对象!
这里的key是一个巧妙地设计 
user:{id}:{filed}
mset user:1:name zhangsan user:1:age 22
mget user:1:name user:1:age

组合命令 getset  先get然后再set
getset db redis   如果不存在值则 返回null
如果存在值,则获取原来的值,并设置新的值(覆盖原来的)

String类似的使用场景value除了是我们的字符串还可以是我们的数字

代码语言:javascript复制
	   计数器
	
	   统计数量

List

基本的数据类型,列表

在Redis中我们可以把list当做栈,队列,阻塞队列!

所有的list命令都是l开头的

代码语言:javascript复制
放入值 push
lpush list one    将一个或多个值,插入到列表的头部(左)
rpush list two    将一个值或多个值,插入到列表的尾部(右)
lrange list 0  1  获取list中的值 通过区间获取具体的值  
取出 pop
lpop  移除列表的第一个元素
rpop  移除列表的最后一个元素
获取下标
lindex list 1  通过下表获取list中得某一个值
长度
llen  list  返回列表的长度
移除指定的值  lrem
取关   uid
lrem  list 1  one  移除list中指定个数的value,精确匹配
修剪 trim
ltrim list 1  2  通过下标截取指定的长度 这个list已经被改变了  只剩下截取的元素
rpoplpush  移除列表的最后一个元素将它移动到新的列表中
rpoplpush mylist myotherlist  
lrange mylist 0 -1  查看原来的列表
lrange myotherlist 0 -1查看目标列表中,确实存在该值


**lset 将列表中指定下标的值替换为另外一个值**

exists list 判断这个列表是否存在
lset list 0 item 如果不存在列表我们去更新就会报错 如果存在就会更新当前下标的值



linsert   将某个具体的value插入到列表中某个元素的前面或者后面  前面before  后面after
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> linsert list  after value1 other
(integer) -1
127.0.0.1:6379> linsert list after item other
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "item"
2) "other"

总结 :

实际上是一个链表

before node after ,left和right都可以插入值

如果key不存在,创建新的链表

如果key存在新增内容

如果移除了key所有的value都消失了 空链表也代表不存在

Set(集合 值不能重复)

代码语言:javascript复制
sadd myset hello  set集合中添加元素
smembers myset   查看指定set集合的所有值



127.0.0.1:6379> sismember myset feifei  判断某一个值是不是在set中
如果set集合中存在 feifei返回1    
(integer) 1
127.0.0.1:6379> sismember myset hah  如果set集合中不存在hah返回0
(integer) 0

127.0.0.1:6379> scard myset  获取set集合中的元素个数
(integer) 2
127.0.0.1:6379> sadd myset feifei set集合不能添加相同的元素
(integer) 0
127.0.0.1:6379> sadd myset love   
(integer) 1
127.0.0.1:6379> scard myset  
(integer) 3

移除元素

代码语言:javascript复制
127.0.0.1:6379>  srem myset love  移除set集合中的指定元素
(integer) 1
127.0.0.1:6379> scard myset   
(integer) 2
127.0.0.1:6379> smembers myset
1) "feifei"
2) "hello

set无序不重复集合 抽取随机元素

代码语言:javascript复制
127.0.0.1:6379> srandmember myset 随机抽取一个元素
1) "hello"
127.0.0.1:6379> srandmember myset 1  随机抽取指定个数的元素
1) "hello"
127.0.0.1:6379> srandmember myset 1
1) "feifei"

删除指定的key随即删除key!

代码语言:javascript复制
127.0.0.1:6379> smembers myset
1) "feifei"
2) "hello"
127.0.0.1:6379> spop myset 随机删除set集合中得元素
"hello"
127.0.0.1:6379> spop myset
"feifei"
127.0.0.1:6379> smembers myset
(empty list or set)

将一个指定的值,移动到另外一个set集合中

代码语言:javascript复制
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd myset feifei      添加元素
(integer) 1
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset love
(integer) 1
127.0.0.1:6379> sadd myset2 feifei2    在myset2集合中添加一个  feifei2 元素
(integer) 1
127.0.0.1:6379> smove myset  myset2 feifei       移动  myset中的元素 feifei 到myset2中
(integer) 1
127.0.0.1:6379> smembers myset2
1) "feifei"
2) "feifei2"

微博 共同好友(交集)

数字集合类 :

-差集 sdiff key1 key2 第一个集合中的元素减去第二个集合中的元素剩余的一集合中的元素

就是第一个集合中有,第二个集合中没有的元素

代码语言:javascript复制
127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key1 d
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> sdiff key1 key2
1) "b"
2) "a"

-交集

集合1 和 集合2 相同的元素

代码语言:javascript复制
sinter key1 key2    
1) "c"
2) "d"

-并集

并集 集合1和集合2所有的元素加在一起

代码语言:javascript复制
127.0.0.1:6379> sunion key1 key2
1) "a"
2) "d"
3) "b"
4) "c"
5) "e"

例:wei博中,A用户将所有关注的人放在一个set集合中,将它的粉丝也放在一个集合中!

共同关注 , 取并集就可以了

共同关注,共同爱好等等

Hash(哈希 )

例如map集合 本质和String类型没有太大区别,还是一个简单的key-value!

key- 集合 这时候值是一个map集合

set myhash field feifei

代码语言:javascript复制
127.0.0.1:6379> hset myhash field1 feifei 向myhash中放入一个  field1 feifei 键值对
(integer) 1
127.0.0.1:6379> hget myhash field1
"feifei"    取出键field1中的值
127.0.0.1:6379> hmset myhash field1 hello field2 world
OK     批量放入多个键值对
127.0.0.1:6379> hmget myhash field1 field2
1) "hello"        批量取出多个键对应的值
2) "world"
127.0.0.1:6379> hgetall myhash
1) "field1"                取出myhash中所有键值对
2) "hello"
3) "field2"
4) "world"
删除    
127.0.0.1:6379> hdel myhash field2    删除hash指定的key字段!对应的value值也就消失了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"

查看长度

代码语言:javascript复制
127.0.0.1:6379> hlen myhash   查看myhash的长度
(integer) 1

判断hash中的指定字段是否存在

代码语言:javascript复制
127.0.0.1:6379>  hexists  myhash field1
(integer) 1
127.0.0.1:6379> hexists myhash field2
(integer) 0

只获得所有的field

代码语言:javascript复制
127.0.0.1:6379> hkeys myhash
1) "field1"

获得所有的value

代码语言:javascript复制
127.0.0.1:6379> hvals myhash
1) "hello"

127.0.0.1:6379> hset myhash field2 2   向myhash表中设置  key value
(integer) 1
127.0.0.1:6379> hincrby myhash field2 2   自增2
(integer) 4
127.0.0.1:6379> hincrby myhash field2 -1  自增-1相当于-1
(integer) 3
127.0.0.1:6379> hsetnx myhash field2 hello  如果不存在可以设置值  如果存在不能设置  这里我们field2存在了所以设置失败
(integer) 0

用户信息的保存 hash更适合对象的存储 String更加适合字符串的存储

代码语言:javascript复制
127.0.0.1:6379> hset user:1 name feifei
(integer) 1
127.0.0.1:6379> hget user:1 name
"feifei"

Zset(有序集合)

在set的基础上增加了一个值 set k1 v1 zset k1 score1 v1 可以排序

添加

代码语言:javascript复制
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"

排序实现

代码语言:javascript复制
127.0.0.1:6379> zrange salary 0 -1 withscores    从小到大排序  并且附带成绩
1) "xiaozhang"
2) "2500"
3) "zhangsan"
4) "3000"
5) "feifei"
6) "10000"
代码语言:javascript复制
zrange salary 0 -1 显示全部用户从小到大
代码语言:javascript复制
127.0.0.1:6379> zrevrange salary 0 -1   从大到小排序
1) "feifei"
2) "xiaozhang"
    
127.0.0.1:6379> zrange salary 0 -1 withscores 获得成员按分数值递增  从小到大 排列的排名。
1) "xiaozhang"
2) "2500"
3) "feifei"
4) "10000"

获取元素个数

代码语言:javascript复制
127.0.0.1:6379> zcard salary
(integer) 2

获取指定区间的成员数量

代码语言:javascript复制
127.0.0.1:6379> zcount salary 500  3000
(integer) 1

使用场景:排序 存储班级成绩表 工资表排序!

普通消息1 重要消息2 带权重判断

排行榜实现

三种特殊关系数据类型

geospatial(地理位置)

定位 附近的人 两地点之间的距离

redis的Geo可以查询一些测试数据 3.2版本推出 这个功能可以推算地理位置的信息 两地之间的距离 附近的人

代码语言:javascript复制
  命令                        	描述                            
  Redis GEOHASH 命令          	返回一个或多个位置元素的 Geohash 表示       
  Redis GEOPOS 命令           	从key里返回所有给定位置元素的位置(经度和纬度)     
  Redis GEODIST 命令          	返回两个给定位置之间的距离                 
  Redis GEORADIUS 命令        	以给定的经纬度为中心, 找出某一半径内的元素        
  Redis GEOADD 命令           	将指定的地理空间位置(纬度、经度、名称)添加到指定的key中
  Redis GEORADIUSBYMEMBER 命令	找出位于指定范围内的元素,中心点是由给定的位置元素决定   

geoadd 添加地理位置 (经度 纬度 名称 )添加到指定的key中

规则 : 两级无法直接添加我们一般会下载城市数据 直接通过java一次性导入

代码语言:javascript复制
127.0.0.1:6379> geoadd china:city 120.153576 30.287459 hangzhou   添加地理位置
(integer) 1
127.0.0.1:6379> geoadd china:city 126.642464 45.756967 harbin
(integer) 1
127.0.0.1:6379> geoadd china:city 116.405285 39.904989 beijing
(integer) 1

geopos

获得地点的定位 一个坐标值

代码语言:javascript复制
127.0.0.1:6379> geopos china:city beijing   获取指定城市的经度和纬度
1) 1) "116.40528291463852"
   2) "39.904988422912503"

geodist返回两个地点之间的距离

如果两个位置之间的其中一个不存在, 那么命令返回空值。

指定单位的参数 unit 必须是以下单位的其中一个:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。

GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。

代码语言:javascript复制
127.0.0.1:6379> geodist china:city beijing hangzhou  查看北京到杭州的直线距离
"1122483.2754"                                     
127.0.0.1:6379> geodist china:city beijing hangzhou m  查看北京到杭州的直线距离 单位为米
"1122483.2754"                                      
127.0.0.1:6379> geodist china:city beijing hangzhou km  查看北京到杭州的直线距离 单位为km
"1122.4833"

附近的人

1.获得所有附近的人的地址 通过半径来查询

georedius 以给定的经纬度为中心 找出某一半径内的元素 所有的数据应该录入到China:city中

代码语言:javascript复制
127.0.0.1:6379> georadius china:city 110 30 1000 km  查找 经纬度 110 30 半径1000km内的城市
1) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 1000 km  withdist   查找 经纬度 110 30 withdist显示到中心距离的位置
 georadius china:city 120 40 1000 km withdist withcoord  显示他人的定位信息 
 1) 1) "beijing"
   2) "306.6596"
   3) 1) "116.40528291463852"
      2) "39.904988422912503"
2) 1) "harbin"
   2) "837.9133"
   3) 1) "126.64246469736099"
      2) "45.756967600949636"

查询一个城市一定范围内所有的城市

代码语言:javascript复制
127.0.0.1:6379> georadiusbymember china:city hangzhou 1000 km  以杭州为中心1000km内的城市
1) "hangzhou"

geohash 返回一个或多个位置元素的geohash表示

该命令将返回11个字符的Geohash字符串!

代码语言:javascript复制
127.0.0.1:6379> geohash china:city beijing harbin  将二维的经纬度转换为一维的字符串
1) "wx4g0b7xrt0"
2) "yb4h3cf1xk0"

geo的实现原理其实就是zset有序集合 我们可以使用zset操作geo

代码语言:javascript复制
127.0.0.1:6379> zrem china:city shanghai 移除城市中的上海
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1 查看地图中所有的元素
1) "hangzhou"
2) "shanghai"    

hyperloglog(基数)

什么是基数? 一个集合内不重复的数就是基数

a{1,3,5,7,8,7}

b{1,3,5,7,8}

基数(不重复的元素)=5

Rdies Hyperloglog 基数统计的算法

优点占得内存是固定的

网页的uv(一个人访问一个网站多次但还是算作一个人!)

传统的方式 set保存用户的id, 然后就可以统计set中的元素数量作为标准判断!

这个方式保存大量的用户id 比较麻烦! 我们的目的是为了计数而不是为了保存用户id;

使用:

代码语言:javascript复制
127.0.0.1:6379> pfadd mykey  a b c d e f   添加第一组元素
(integer) 1
127.0.0.1:6379> pfcount mykey   统计mykey中基数数量
(integer) 6
127.0.0.1:6379> pfadd mykey1 a b c d e e f   添加第二组元素
(integer) 1
127.0.0.1:6379> pfcount mykey1    
(integer) 6
127.0.0.1:6379> pfmerge mykey2 mykey mykey1  合并两组元素(并集)
OK
127.0.0.1:6379> pfcount mykey2   查看并集的数量
(integer) 6

如果允许容错 那么一定可以使用hyperloglog!

如果不允许容错,就使用set或者自己的数据类型即可

bitmaps(位图)

位存储

统计用户信息 分为活跃和不活跃

登录 未登录!

bitmaps位图数据结构 操作二进制数来记录只有0和1 两个状态

记录周一到周日的打卡

打卡 : 1 没打卡 :0

代码语言:javascript复制
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 0
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 6 1
(integer) 0

查看某一天是否有打卡

代码语言:javascript复制
127.0.0.1:6379> getbit sign 1  查看第二天
(integer) 1
127.0.0.1:6379> getbit sign 2  查看第三天
(integer) 0

统计打卡天数!

代码语言:javascript复制
127.0.0.1:6379> bitcount sign
(integer) 5

0 人点赞