Redis 数据类型


Redis系列笔记跟着B站up狂神说学习,所有笔记照着敲了一遍,记录下来供后续忘了参考。


一、NoSQL简介
二、Redis入门–配置安装等
三、Redis数据类型(重要)
四、Redis事务
五、Jedis使用
六、SpringBoot整合Redis
七、Redis持久化


Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和地理空间(geospatial) 索引半径查询。 Redis 内置了复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)。

Redis-Key

常用的命令

 FLUSHALL              # 清空所有数据库
 FLUSHDB               # 清空当前数据库
 keys *                # 查看所有的key
 EXISTS name           # 查看这个name是否存在
 set name huage        # 设置key-value
 get name              # 使用key 获取value
 del name              # 通过key删除
 EXPIRE name 10        # 设置key的过期时间
 ttl name              # 查看还有多久过期,-2为已过期,单位为s
 type name             # 获取key-value的类型

五大基本类型

Redis-Key

常用的命令

 FLUSHALL              # 清空所有数据库
 FLUSHDB               # 清空当前数据库
 keys *                # 查看所有的key
 EXISTS name           # 查看这个name是否存在
 set name huage        # 设置key-value
 get name              # 使用key 获取value
 del name              # 通过key删除
 EXPIRE name 10        # 设置key的过期时间
 ttl name              # 查看还有多久过期,-2为已过期,单位为s
 type name             # 获取key-value的类型

String

127.0.0.1:6379> set key v1       #设置值
OK
127.0.0.1:6379> get key1         #获取值
(nil)
127.0.0.1:6379> get key
"v1"
127.0.0.1:6379> EXISTS key       #看值是否存在
(integer) 1
127.0.0.1:6379> APPEND key 23    #append字符串
(integer) 4
127.0.0.1:6379> get key
"v123"
127.0.0.1:6379> STRLEN key       #获取字符串长度
(integer) 4

#################################
# i++ 和 i+=n
127.0.0.1:6379> set views 0      
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views       #浏览量增加1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> decr views       #浏览量减1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> INCRBY views 5   #增加5
(integer) 6
127.0.0.1:6379> DECRBY views 2	 #减少2步长
(integer) 4

################################
# 字符串范围 range--substring(java)
127.0.0.1:6379> set name mynameishuage
OK
127.0.0.1:6379> GETRANGE name 0 3    # 截取字符串从0到第3位,闭区间
"myna"
127.0.0.1:6379> GETRANGE name 0 -1   # 获取全部的字符串==get key一样
"mynameishuage"

###############################
# 替换指定位置的字符串
127.0.0.1:6379> set name2 abcdefg
OK
127.0.0.1:6379> SETRANGE name2 1 xx  # 从第一位开始,后面两个位置数据变成xx
(integer) 7
127.0.0.1:6379> get name2
"axxdefg"

###############################
# setex (set with expire)    # 设置过期时间
# setnx (set if not exist)   # 不存在设置
127.0.0.1:6379> SETEX name3 30 "abcdefg"  # 设置过期时间 30s后过期
OK
127.0.0.1:6379> get name3
"abcdefg"
127.0.0.1:6379> setnx mykey "redis"       # 如果mykey不存在,创建mykey
(integer) 1
127.0.0.1:6379> ttl name3                 # 查看key的剩余时间
(integer) -2
127.0.0.1:6379> setnx mykey "mongodb"     # 如果mykey存在,创建失败
(integer) 0
127.0.0.1:6379> get mykey
"redis"

################################
# mset 同时设置多个值
# mget 同时获取多个值
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3   # 同时设置多个值
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
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       # mset是一个原子性的操作,要么一起成功,要么一起失败
(integer) 0
127.0.0.1:6379> get k4
(nil)

##################################
#对象 设置一个user:1 对象,值为 json 字符来保存一个对象!
# 这里的key是一个巧妙的设计 user:{id}:{filed}
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 12
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "12"

#################################
# getset
127.0.0.1:6379> getset kk vv    # 如果不存在,则返回nil
(nil)
127.0.0.1:6379> get kk
"vv"
127.0.0.1:6379> getset kk mm    # 如果存在,则返回原来的值,并设置新的值
"vv"
127.0.0.1:6379> get kk
"mm"

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

  • 计数器
  • 统计多单位的数量
  • 对象缓存存储

List

基本的数据类型,列表

在Redis里面,可以把list当成栈,队列 ,阻塞队列

所有的list命令都是 lorr开头的,Redis不区分大小写

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 two
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "two"
3) "one"
127.0.0.1:6379> RPUSH list three    # 将一个或者多个值,放在列表的尾部(右边)
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "two"
3) "one"
4) "three"

################################
# LPOP
# RPOP
127.0.0.1:6379> LPOP list               # 移除列表头部
"two"
127.0.0.1:6379> RPOP list				# 移除列表尾部
"three"
127.0.0.1:6379> LRANGE list 0 -1        # 获取所有的值, 0,-1
1) "two"
2) "one"

################################
Lindex
127.0.0.1:6379> Lindex list 1
"two"
127.0.0.1:6379> Lindex list 0
"two"
127.0.0.1:6379> Lindex list 2
"one"
127.0.0.1:6379> Lindex list 3
(nil)

################################
# Llen
127.0.0.1:6379> LLEN list               # 查看list长度
(integer) 3

################################
# 移除指定的值
# lrem key 数量 value
127.0.0.1:6379> LREM list 1 two         # 移除list里面一个叫two的值
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> LREM list 1 one
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1 
1) "two"

################################
# ltrim 截取指定 [a, b] 的list
127.0.0.1:6379> lpush mylist hello
(integer) 1
127.0.0.1:6379> lpush mylist hello1
(integer) 2
127.0.0.1:6379> lpush mylist hello2
(integer) 3
127.0.0.1:6379> lpush mylist hello3
(integer) 4
127.0.0.1:6379> lpush mylist hello4
(integer) 5
127.0.0.1:6379> ltrim mylist 1 3               # 通过下标截取指定的长度,但是这个list已经被改变了,只剩下了截取之后的元素!
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello3"
2) "hello2"
3) "hello1"

##############################
#rpoplpush 移除列表中的最后一个元素到另外一个列表中
127.0.0.1:6379> rpoplpush mylist myother
"hello1"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello3"
2) "hello2"
127.0.0.1:6379> lrange myother 0 -1
1) "hello1"

##############################
#lset 将列表中指定下标真的值替换成另外一个值
127.0.0.1:6379> lpush list v1
(integer) 1
127.0.0.1:6379> lset list 0 vv            # 将第0个位置的值替换成vv
OK
127.0.0.1:6379> lrange list 0 -1
1) "vv"
127.0.0.1:6379> lset list 1 v2            # 替换值的时候需要这个列表的位置存在
(error) ERR index out of range

##############################
# linsert 将某一个值插入在列表中某个元素的前面或者后面
127.0.0.1:6379> linsert list before vv other   # 前面
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "other"
2) "vv"
127.0.0.1:6379> linsert list after vv after   # 后面
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "other"
2) "vv"
3) "after"
127.0.0.1:6379> linsert list after v after   # 没有这个值插入失败
(integer) -1

小结

  • 他其实是一个链表, before Node after, left, right 都可以插入值
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有值,空链表,也代表不存在!
  • 在两边插入或者改动值,效率最高! 插入中间,相对效率会低一点。
Set
127.0.0.1:6379> sadd myset abc          # 添加元素到集合中
(integer) 1
127.0.0.1:6379> SMEMBERS myset			# 查看集合中的元素
1) "abc"
127.0.0.1:6379> SISMEMBER myset abc		# 查看该元素时候在集合中
(integer) 1
127.0.0.1:6379> SCARD myset				# 查看集合中元素的个数
(integer) 1
127.0.0.1:6379> sadd myset eee
(integer) 1
127.0.0.1:6379> SCARD myset
(integer) 2
127.0.0.1:6379> SMEMBERS myset
1) "abc"
2) "eee"

#################################
127.0.0.1:6379> SADD myset abc			# 添加相同的元素失败
(integer) 0
127.0.0.1:6379> SADD myset aaa
(integer) 1
127.0.0.1:6379> srem myset eee 			# 移除元素
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "abc"
2) "aaa"

################################
# 随机抽选一个元素(例如抽奖就可以直接使用)
127.0.0.1:6379> SRANDMEMBER myset		# 随机抽选一个元素
"aaa"
127.0.0.1:6379> SRANDMEMBER myset
"abc"
127.0.0.1:6379> SRANDMEMBER myset 2		# 随机抽选n个元素
1) "abc"
2) "aaa"

################################
# 删除指定的key, 随机删除key
127.0.0.1:6379> spop myset [count] 		# 随机删除一个或者多个元素
"qwer"
127.0.0.1:6379> SMEMBERS myset 
1) "abc"
2) "aaa"
3) "pppp"

################################
127.0.0.1:6379> sadd myset2 kkk
(integer) 1
127.0.0.1:6379> sadd myset2 hhh
(integer) 1
127.0.0.1:6379> SMEMBERS myset2
1) "kkk"
2) "hhh"
127.0.0.1:6379> smove myset2 myset hhh		# 将set2的元素hhh移动到set1里面
(integer) 1
127.0.0.1:6379> SMEMBERS myset2
1) "kkk"
127.0.0.1:6379> SMEMBERS myset
1) "abc"
2) "hhh"
3) "aaa"
4) "pppp"

###############################
# 数字集合类
- 差集 = 并 - 交   sdiff
- 交集   			sinter
- 并集			sunion

127.0.0.1:6379> sadd s1 a-e
127.0.0.1:6379> sadd s2 a-b

127.0.0.1:6379> SDIFF s1 s2			# 差集
1) "c"
2) "d"
3) "e"
127.0.0.1:6379> SINTER s1 s2		# 交集(共同好友)
1) "b"
2) "a"
127.0.0.1:6379> SUNION s1 s2		# 并集
1) "b"
2) "c"
3) "d"
4) "e"
5) "a"

Hash

Map集合,(key-value) To key-map! 这里的值是一个map集合,本质和String类型没有什么区别,还是和 key-value 一样。

127.0.0.1:6379> HSET myhash field1 huage		# set 一个具体的 key-value
(integer) 1
127.0.0.1:6379> HGET myhash field1				# 获取一个字段值
"huage"
127.0.0.1:6379> hmset myhash field1 hello field2 word		# set 多个 key-value
OK
127.0.0.1:6379> hmget myhash field1 field2 		# 获取多个字段
1) "hello"
2) "word"
127.0.0.1:6379> HGETALL myhash 					# 获取全部的数据
1) "field1"
2) "hello"
3) "field2"
4) "word"
127.0.0.1:6379> HDEL myhash field1				# 删除hash制定的key字段
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "field2"
2) "word"
######################################
# hlen
# HEXISTS
127.0.0.1:6379> HLEN myhash						# 获取hash的长度
(integer) 1
127.0.0.1:6379> HEXISTS myhash fi				# 判断field是否存在
(integer) 0
######################################
127.0.0.1:6379> HKEYS myhash					# 只获取所有key
1) "field2"
127.0.0.1:6379> HVALS myhash					# 只获取所有value
1) "word"

#####################################
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 yes		# 如果不存在则可以设置
(integer) 1
127.0.0.1:6379> HSETNX myhash field4 no			# 如果存在设置失败
(integer) 0
127.0.0.1:6379> HGETALL myhash
1) "field2"
2) "word"
3) "field3"
4) "5"
5) "field4"
6) "yes"

hash变更的数据 user name age,尤其是用户信息之类的,经常变更的信息

hash更适合存储对象,String适合存储字符串!

Zset(有序集合)

在set的基础上增加了一个值 set k1 v1zset k1 score v1

127.0.0.1:6379> zadd zs1 1 one					# 添加一个值
(integer) 1
127.0.0.1:6379> zadd zs1 2 two 3 three			# 添加多个值
(integer) 2
127.0.0.1:6379> ZRANGE zs1 0 -1					# 获取所有值
1) "one"
2) "two"
3) "three"

#####################################
127.0.0.1:6379> zadd salary 5000 xiaoming		# 添加三个人的薪水
(integer) 1
127.0.0.1:6379> zadd salary 250 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 1500 zhangsan
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf	# 从小到大排序
1) "xiaohong"
2) "zhangsan"
3) "xiaoming"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 4000 withscores    # 排序到限制值带上数字
1) "xiaohong"
2) "250"
3) "zhangsan"
4) "1500"
#################################
127.0.0.1:6379> zrem salary xiaoming			# 删除元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1				# 显示所有元素
1) "xiaohong"
2) "zhangsan"
127.0.0.1:6379> ZREVRANGE salary 0 -1			# 翻转显示
1) "zhangsan"
2) "xiaohong"
127.0.0.1:6379> zcard salary					# 获取set中元素的个数
(integer) 2
127.0.0.1:6379> ZCOUNT salary 1000 3000			# 获取区间里面的元素的个数
(integer) 1

三种特殊类型

geospatial 地理位置

image-20200702204214015

# 添加经纬度-城市
# 规则: 两级无法直接添加,我们一般是下载城市数据,通过java直接导入
# 参数:将指定的地理空间位置(经度、纬度、名称)添加到指定的key中。
# 有效的经度从-180度到180度。有效的纬度从-85.05112878度到85.05112878度。
127.0.0.1:6379> geoadd china:city 116.40 39.90 peking
(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 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 114.05 22.52 shengzhen
(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 108.96 34.26 xian
(integer) 1

##########################
# GEOPOS 获取指定城市的经纬度
127.0.0.1:6379> GEOPOS china:city peking chongqing
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "106.49999767541885376"
   2) "29.52999957900659211"
#############################
# GEODIST 获取两个位置的距离  时间复杂度:O(log(N))
# 参数: key member1 member2 [unit]

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

127.0.0.1:6379> GEODIST china:city peking chongqing
"1464070.8051"
127.0.0.1:6379> GEODIST china:city peking chongqing km
"1464.0708"

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]

附近的人??(获取附近的人的地址,定位)通过半径来查询

127.0.0.1:6379> GEORADIUS china:city 110 30 500 km			# 获取该经纬度距离500km内的城市
1) "chongqing"
2) "xian"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist #显示城市+距离
1) 1) "chongqing"
   2) "341.9374"
2) 1) "xian"
   2) "483.8340"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord  # 显示城市+经纬度
1) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord count 1 # 筛选出指定的结果
1) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"

找出位于指定元素周围其他元素

GEORADIUSBYMEMBER

127.0.0.1:6379> GEORADIUSBYMEMBER china:city peking 1000 km
1) "peking"
2) "xian"
HyperLogLog

什么是基数?

A{1, 3, 5, 7, 9, 7} —5

B{1, 3, 5, 7, 8} —5

基数:一个集合内不重复的元素就是基数

简介

Redis HyperLogLog 基数统计的算法

优点: 占用的内存是固定的, 2 64 2^{64} 264个不同的元素,只需要 12kb内存,如果从内存的角度来选择是首选。

使用场景:网页的UV(一个人访问一个网站多次,但还是算作一个人!)

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

这个方式如果保存了大量的用户id,就会比较麻烦,我们的目的是为了计数,而不是为了保存用户id。

127.0.0.1:6379> PFADD mykey a b c d e f g h			# 添加
(integer) 1
127.0.0.1:6379> PFADD mykey2 l o p n j k u y
(integer) 1
127.0.0.1:6379> PFCOUNT mykey						# 统计
(integer) 8
127.0.0.1:6379> PFCOUNT mykey2
(integer) 8
127.0.0.1:6379> PFMERGE mykey3 mykey mykey2			# 合并
OK
127.0.0.1:6379> PFCOUNT mykey3
(integer) 16
Bitmaps

位存储

Bitmaps 位图,数据结构!都是操作二进制位来进行记录,就只有0和1两个状态!

127.0.0.1:6379> setbit sign 0 0
(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 1
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
###########################
# 获取状态
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 2
(integer) 0
##########################
# 统计记录
127.0.0.1:6379> bitcount sign
(integer) 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值