Redis-06-五大基本(三大特殊)数据类型详解

Redis-06-五大基本(三大特殊)数据类型详解

Redis是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件

它支持多种类型的数据结构,如字符串(String),散列(Hash),列表(List),集合(Set),有序集合(Sorted Set或者是ZSet)与范围查询,Bitmaps,Hyperloglogs 和地理空间(Geospatial)索引半径查询。

其中常见的数据结构类型有:String、List、Set、Hash、ZSet这5种。

Redis 内置了复制(Replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(Transactions) 和不同级别的磁盘持久化(Persistence),并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(High Availability)。

1.五大数据类型

String(字符串)

汇总:
set name xkx # 设置值
get name	# 获取值
EXISTS name # 判断指定key是否存在
APPEND name hello # 往指定key中追加字符,如果key不存在则自动创建
STRLEN name # 查看指定key长度
INCR views # 自增1,也就是浏览量+1
DECR views # 自减1,也就是浏览量-1
INCRBY views 10 # 步长,指定增量为10,相当于浏览量+10
DECRBY views 5 # 步长,指定减量为5,相当于浏览量-5
GETRANGE name 0 3 # 截取字符串 [0,3]
GETRANGE name 0 -1 # 获取字符串,相当于get name
SETRANGE name 1 xx # 替换指定位置开始的字符串
setex name 30 hello # 设置name的值为hello,30秒后过期
setnx mykey redis # 如果mykey不存在,创建成功,存在则失败
mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
mget k1 k2 k3 # 同时获取多个值
# msetnx 如果key不存在才创建
msetnx k1 v1 k4 v4 # msetnx是一个原子性操作,要么都成功,要么都失败
set user:1 {name:zhangsan,age:3} # 设置一个user:1对象 ,值为json字符来保存一个对象

# 这里的key是一个巧妙地设计 user:{id}:{diled},如此设计在Redis中是完全OK的
mset user:2:name zhangsan user:2:age 2
mget user:2:name user:2:age
# 先获取db的值,在设置db=redis
getset db redis # 如果不存在,返回nil,并创建新的key
实例:
########################################################################
127.0.0.1:6379> set name xkx # 设置值
OK
127.0.0.1:6379> get name	# 获取值
"xkx"
127.0.0.1:6379> EXISTS name # 判断指定key是否存在
(integer) 1
127.0.0.1:6379> APPEND name hello # 往指定key中追加字符,如果key不存在则自动创建
(integer) 8
127.0.0.1:6379> get name 
"xkxhello"
127.0.0.1:6379> STRLEN name # 查看指定key长度
(integer) 8
########################################################################
# 浏览量应用
127.0.0.1:6379> set views 0 # views为浏览量,初始为0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> INCR views # 自增1,也就是浏览量+1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> INCR views
(integer) 2
127.0.0.1:6379> DECR views # 自减1,也就是浏览量-1
(integer) 1
127.0.0.1:6379> INCR views
(integer) 2
127.0.0.1:6379> INCR views
(integer) 3
127.0.0.1:6379> INCR views
(integer) 4
127.0.0.1:6379> DECR views
(integer) 3
127.0.0.1:6379> DECR views
(integer) 2
127.0.0.1:6379> DECR views
(integer) 1
127.0.0.1:6379> DECR views
(integer) 0
127.0.0.1:6379> DECR views
(integer) -1
127.0.0.1:6379> get views
"-1"
127.0.0.1:6379> INCRBY views 10 # 步长,指定增量为10,相当于浏览量+10
(integer) 9
127.0.0.1:6379> INCRBY views 10
(integer) 19
127.0.0.1:6379> DECRBY views 5 # 步长,指定减量为5,相当于浏览量-5
(integer) 14
########################################################################
# 截取字符串 range
127.0.0.1:6379> set name xkxfyy123
OK
127.0.0.1:6379> get name
"xkxfyy123"
127.0.0.1:6379> GETRANGE name 0 3 # 截取字符串 [0,3]
"xkxf"
127.0.0.1:6379> GETRANGE name 0 -1 # 获取字符串,相当于get name
"xkxfyy123"

# 替换字符串 
127.0.0.1:6379> set name abcdefghijklmn
OK
127.0.0.1:6379> get name
"abcdefghijklmn"
127.0.0.1:6379> SETRANGE name 1 xx # 替换指定位置开始的字符串
(integer) 14
127.0.0.1:6379> get name
"axxdefghijklmn"
########################################################################
# setex(set with expire) 	# 设置过期时间
# setnx (set if not exist)  # 如果不存在则设置

127.0.0.1:6379> setex name 30 hello # 设置name的值为hello,30秒后过期
OK
127.0.0.1:6379> ttl name
(integer) 27
127.0.0.1:6379> get name
"hello"
127.0.0.1:6379> setnx mykey redis # 如果mykey不存在,创建成功
(integer) 1
127.0.0.1:6379> keys *
1) "mykey"
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> setnx mykey mongoDB # 如果mykey存在,创建失败
(integer) 0
127.0.0.1:6379> keys *
1) "mykey"
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> keys *
1) "k3"
2) "k2"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3 # 同时获取多个值
1) "v1"
2) "v2"
3) "v3"								# msetnx 如果key不存在才创建
127.0.0.1:6379> msetnx k1 v1 k4 v4 # msetnx是一个原子性操作,要么都成功,要么都失败
(integer) 0
127.0.0.1:6379> get k4
(nil)

#对象
set user:1 {name:zhangsan,age:3} # 设置一个user:1对象 ,值为json字符来保存一个对象

# 这里的key是一个巧妙地设计 user:{id}:{diled},如此设计在Redis中是完全OK的

127.0.0.1:6379> mset user:2:name zhangsan user:2:age 2
OK
127.0.0.1:6379> mget user:2:name user:2:age
1) "zhangsan"
2) "2"

########################################################################
getset # 先get再set
								# 先获取db的值,在设置db=redis
127.0.0.1:6379> getset db redis # 如果不存在,返回nil,并创建新的key
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongoDB # 如果存在值,先获取旧值,再设置新值
"redis"

案例思路

String类似的使用场景:value可以是字符串或数字!!!

-     计数器
-     统计多单位的数量
-     粉丝数
-     对象缓存存储!

List(列表)

是列表,但是在Redis中,我们可以把list弄成栈,队列,阻塞队列!

所有的LIst命令都是L开头的(不区分大小写)

汇总
LPUSH list one  	# 将一个值或者多个值,插入到列表头部(左)
LRANGE list 0 -1	# 获取list中的所有值
LRANGE list 0 1		# 通过区间获取具体值
RPUSH list right 	# 将一个值或者多个值,插入到列表尾部(右)
LPOP  list  		# 移除list的第一个元素
RPOP list  			# 移除list的最后一个元素
LINDEX list 1  		#通过下标获取具体值(起始为0)
LLEN list 			# 返回列表长度
LREM list 2 three 	# 移除2个three,从头开始,因为里面只有1个了,所以返回1
LTRIM myList 1 2    # 通过下标截取指定的长度,保留[1,2]内容
RPOPLPUSH mylist myotherlist 	# 移除mylist列表最后一个元素,并且移动到另外一个myotherlist中
lset list 0 item    # 修改指定下标处的值,如果列表或下标处不存在就会报错
LINSERT list before hello other # 将other插入到hello前面
LINSERT list after hello2 after # 将after插入到hello2后面
实例
########################################################################
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 # 获取list中的值
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 right # 将一个值或者多个值,插入到列表尾部(右)
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"

########################################################################
LPOP
RPOP
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> LPOP  list  # 移除list的第一个元素
"three"
127.0.0.1:6379> RPOP list  # 移除list的最后一个元素
"right"
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
########################################################################
Lindex
127.0.0.1:6379> LINDEX list 1  #通过下标获取具体值(起始为0)
"one"
127.0.0.1:6379> LINDEX list 0  
"two"
########################################################################
Llen
127.0.0.1:6379> LLEN list # 返回列表长度
(integer) 2
########################################################################
移除指定的值!!!!!
取关 uuid

Lrem
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> LREM list 1 three # 移除1个three,从头开始
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> LREM list 2 three # 移除2个three,从头开始,因为里面只有1个了,所以返回1
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "two"

########################################################################
trim 修剪
127.0.0.1:6379> RPUSH myList hello
(integer) 1
127.0.0.1:6379> RPUSH myList hello2
(integer) 2
127.0.0.1:6379> RPUSH myList hello3
(integer) 3								#  0      1       2     3
127.0.0.1:6379> RPUSH myList hello4     # hello hello2 hello3 hello4
(integer) 4
127.0.0.1:6379> LTRIM myList 1 2     # 通过下标截取指定的长度,保留[1,2]内容
OK
127.0.0.1:6379> LRANGE myList 0 -1
1) "hello2"
2) "hello3"
##########################################################################
rpoplpush # 移除列表最后一个元素,并且移动到另外一个list中
127.0.0.1:6379> RPUSH mylist hello
(integer) 1
127.0.0.1:6379> RPUSH mylist hello1
(integer) 2
127.0.0.1:6379> RPUSH mylist hello2
(integer) 3
127.0.0.1:6379> RPOPLPUSH mylist myotherlist # 移除列表最后一个元素,并且移动到另外一个list中
"hello2"
127.0.0.1:6379> LRANGE mylist 0 -1 # 查看原来的列表
1) "hello"
2) "hello1"
127.0.0.1:6379> LRANGE myotherlist 0 -1 # 查看目标列表
1) "hello2"
##########################################################################
# lset  将list中指定下标的值替换为另外一个值,更新操作!
127.0.0.1:6379> EXISTS list			# 判断列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item    # 如果列表不存在就会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> LRANGE list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item # 如果存在,就会替换指定下标处的值
OK
127.0.0.1:6379> LRANGE list 0 0
1) "item"
127.0.0.1:6379> lset list 1 other # 指定下标处如果不存在,也会报错
(error) ERR index out of range
##########################################################################
Linsert # 将具体的值插入到指定值的前面或后面

127.0.0.1:6379> LPUSH list hello
(integer) 1
127.0.0.1:6379> LPUSH list hello2
(integer) 2
127.0.0.1:6379> LINSERT list before hello other
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1
1) "hello2"
2) "other"
3) "hello"
127.0.0.1:6379> LINSERT list after hello2 after
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "hello2"
2) "after"
3) "other"
4) "hello"

小结
  • 他实际上是一个链表,before Node after , left , right都可以插入值
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有值,空链表,也代表不存在!
  • 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点~

可以当作 消息排队!消息队列( Lpush Rpop ) ,栈( Lpush Lpop )

Set(集合)

其中的值不会重复

汇总
SADD myset hello  		# 如果没有,则先创建集合再添加元素,如果有直接添加元素
SMEMBERS myset 			# 查看集合中全部元素
SISMEMBER myset hello 	# 检查集合中存不存再某个元素
SCARD myset 			#获取set集合中元素个数
SREM myset hello 		# 移除set集合中的指定元素
SRANDMEMBER myset		# 随机抽选出一个元素 无序不重复集合!抽随机!
SRANDMEMBER myset 2 	# 随机抽选出指定个数的元素
SPOP myset 				# 随机删除一个元素
SPOP myset 3 			# 随机删除指定个数元素
SMOVE myset myset2 hello1 #将myset集合中hello1的移动到myset2集合中
SDIFF key1 key2  # 两个的差集(以key1为基准)
SINTER key1 key2 # 交集:共同好友就可以这样实现
SUNION key1 key2 # 并集
实例
#########################################################################
SADD
SMEMBERS
SISMEMBER
127.0.0.1:6379> SADD myset hello  # 如果没有,则先创建集合再添加元素,如果有直接添加元素
(integer) 1
127.0.0.1:6379> SADD myset xkx
(integer) 1
127.0.0.1:6379> SADD myset fyy
(integer) 1
127.0.0.1:6379> SMEMBERS myset # 查看集合中全部元素
1) "hello"
2) "fyy"
3) "xkx"
127.0.0.1:6379> SISMEMBER myset hello # 检查集合中存不存再某个元素
(integer) 1
127.0.0.1:6379> SISMEMBER myset world
(integer) 0
#########################################################################
127.0.0.1:6379> SCARD myset #获取set集合中元素个数
(integer) 3
#########################################################################
127.0.0.1:6379> SREM myset hello # 移除set集合中的指定元素
(integer) 1
127.0.0.1:6379> SCARD myset #获取set集合中元素个数
(integer) 2
127.0.0.1:6379> SMEMBERS myset # 查看集合中全部元素
1) "fyy"
2) "xkx"
########################################################################
set 无序不重复集合!抽随机!
127.0.0.1:6379> SRANDMEMBER myset	# 随机抽选出一个元素
"xkx"
127.0.0.1:6379> SRANDMEMBER myset
"xkx"
127.0.0.1:6379> SRANDMEMBER myset
"fyy"
127.0.0.1:6379> SRANDMEMBER myset 2 # 随机抽选出指定个数的元素
1) "fyy"
2) "xkx"
########################################################################
删除指定的key,删除随机key!
127.0.0.1:6379> SMEMBERS myset
1) "xkx"
2) "hello5"
3) "hello"
4) "hello2"
5) "hello3"
6) "hello4"

127.0.0.1:6379> SPOP myset # 随机删除一个元素
"xkx"
127.0.0.1:6379> SPOP myset
"hello2"
127.0.0.1:6379> SPOP myset 3 # 随机删除指定个数元素
"hello"
"hello4"
"hello5"
########################################################################
将一个指定的值移动到另一个set集合中
127.0.0.1:6379> SMEMBERS myset
1) "hello1"
2) "hello4"
127.0.0.1:6379> SADD myset2 set2
(integer) 1
127.0.0.1:6379> SMOVE myset myset2 hello1 #将myset集合中hello1的移动到myset2集合中
(integer) 1
127.0.0.1:6379> SMEMBERS myset2
1) "hello1"
2) "set2"
########################################################################
微博,B站,共同关注!(并集)
数字集合类:
	- 差集	SDIFF
    - 交集	SINTER		共同好友就可以这样实现
    - 并集	SUNION
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 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  # 两个的差集(以key1为基准)
1) "b"
2) "a"
127.0.0.1:6379> SINTER key1 key2 # 交集:共同好友就可以这样实现
1) "c"
127.0.0.1:6379> SUNION key1 key2 # 并集
1) "a"
2) "e"
3) "c"
4) "b"
5) "d"
########################################################################
案例思路

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

共同关注,共同爱好,二度好友,推荐好友!(六度分割理论)

Hash(哈希)

key—Map! 本质和string没有太大区别

汇总
HSET myhash field1 xkx   				# set一个具体的key-value,不可重复
hget myhash field1						# 获取一个字段值
HMSET myhash field1 hello field2 world	#set多个key-value
HMGET myhash field1 field2				#获取多个字段值
HGETALL myhash							# 显示全部数据
HDEL myhash field1 						# 删除指定的字段,对应的value也没了
HLEN myhash 							# 获取内容长度
HEXISTS myhash field2 					# 获取指定字段是否存在
HKEYS myhash 							# 获取所有的field
HVALS myhash 							# 获取所有的value
HINCRBY myhash field3 1 				# 自增 +1
HINCRBY myhash field3 -1 				# 自减 -1
HSETNX myhash field xkx 				# 如果不存在则可以设置,如果存在则不可以设置
实例
################################################################################
127.0.0.1:6379> HSET myhash field1 xkx   # set一个具体的key-value,不可重复
(integer) 1
127.0.0.1:6379> hget myhash field1		# 获取一个字段值
"xkx"
127.0.0.1:6379> HMSET myhash field1 hello field2 world	#set多个key-value
OK
127.0.0.1:6379> HMGET myhash field1 field2	#获取多个字段值
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 # 删除指定的字段,对应的value也没了
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "field2"
2) "world"
################################################################################
hlen
127.0.0.1:6379> HLEN myhash # 获取内容长度
(integer) 1
################################################################################
127.0.0.1:6379> HEXISTS myhash field2 # 获取指定字段是否存在
(integer) 1
################################################################################

127.0.0.1:6379> HKEYS myhash # 获取所有的field
1) "field2"
127.0.0.1:6379> HVALS myhash # 获取所有的value
1) "world"
################################################################################
incr
127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash field3 1 # 自增 +1
(integer) 6
127.0.0.1:6379> HINCRBY myhash field3 -1 # 自减 -1
(integer) 5
127.0.0.1:6379> HSETNX myhash field xkx # 如果不存在则可以设置
(integer) 1
127.0.0.1:6379> HSETNX myhash field xkx # 如果存在则不可以设置
(integer) 0
################################################################################
案例思路

Hash变更的数据 user name age 尤其是用户信息之类的,经常变动的信息!hash更适合对象的存储,String更适合字符串的存储!

127.0.0.1:6379> hset user:1 name xkx
(integer) 1
127.0.0.1:6379> hget user:1 name
"xkx"
127.0.0.1:6379> HMSET user:1 name xkx age 20 
OK
127.0.0.1:6379> HKEYS user:1
1) "name"
2) "age"
127.0.0.1:6379> HVALS user:1
1) "xkx"
2) "20"
127.0.0.1:6379> hget user:1 name
"xkx"
127.0.0.1:6379> hget user:1 age
"20"

Zset(有序集合)

在set的基础上,增加了一个值 set k1 v1 , zset k1 score1 v1

汇总:
ZADD myzset 1 one  			# 添加一个值
ZADD myzset 2 two 3 three   # 添加多个个值
ZRANGE myzset 0 -1
ZRANGEBYSCORE salary -inf +inf 		# 查看负无穷到正无穷的所有值,按工资升序排列
ZREVRANGEBYSCORE salary +inf -inf	# 查看正无穷到负无穷的所有值,按工资降序排列
ZRANGEBYSCORE salary -inf 2500 withscores #负无穷-2500的人排序,并显示信息
ZREM salary lisi  			# 移除有序集合中指定元素
ZCARD salary    			# 获取有序集合中的个数
ZCOUNT salary 500 1100 		#获取指定区间的个数[500,1100],根据score
实例:
127.0.0.1:6379> ZADD myzset 1 one  # 添加一个值
(integer) 1
127.0.0.1:6379> ZADD myzset 2 two 3 three   # 添加多个个值
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "one"
2) "two"
3) "three"
########################################################################
实例:按工资排序(score存储排序根据)
127.0.0.1:6379> ZADD salary 2500 zhangsan  # zhangsan 工资2500
(integer) 1
127.0.0.1:6379> ZADD salary 5000 lisi		#lisi 工资 5000
(integer) 1
127.0.0.1:6379> ZADD salary 1000 xkx		# xkx工资1000
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf # 查看负无穷到正无穷的所有值,按工资升序排列
1) "xkx"
2) "zhangsan"
3) "lisi"
127.0.0.1:6379> ZREVRANGEBYSCORE salary +inf -inf# 查看正无穷到负无穷的所有值,按工资降序排列
1) "lisi"
2) "zhangsan"
3) "xkx"
127.0.0.1:6379> ZRANGEBYSCORE salary 500 2500 # 500-2500 的人排序
1) "xkx"
2) "zhangsan"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores #负无穷-2500的人排序,并显示信息
1) "xkx"
2) "1000"
3) "zhangsan"
4) "2500"
#################################################################################
# 移除rem中的元素
127.0.0.1:6379> ZREM salary lisi  # 移除有序集合中指定元素
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1
1) "xkx"
2) "zhangsan"
127.0.0.1:6379> ZCARD salary     # 获取有序集合中的个数
(integer) 2
####################################################################################
127.0.0.1:6379> ZCOUNT salary 500 1100 #获取指定区间的个数[500,1100],根据score
(integer) 1

案例思路

​ set排序 存储班级成绩表,工资表排序!!!

​ 普通消息 1,重要消息 2,带权重进行判断!!!

​ 排行榜应用实现,取Top N测试!!!

2.三大特殊数据类型

geospatial地理位置

朋友的定位,附近的人,打车距离计算??

Redis的Geo在Redis3.2版本就推出了!这个功能可以推算地理位置信息,两地之间的距离,方圆几里的人!

查询经纬度:http://www.jsons.cn/lngcode/

  • 有效的经度从-180度到180度。
  • 有效的纬度从-85.05112878度到85.05112878度。

当坐标位置超出上述指定范围时,该命令将会返回一个错误。

geoadd
# geoadd 添加城市地理位置
# 规则:南北两极无法添加,我们一般会下载城市数据,使用java程序一次性导入!
# 参数 key 值(经度、纬度、名称)
127.0.0.1:6379> GEOADD Chine:city 116.75192 36.55352 jinan
(integer) 1
127.0.0.1:6379> GEOADD Chine:city 116.80542 35.7599 taian
(integer) 1
127.0.0.1:6379> GEOADD Chine:city 116.43432 37.16632 pingyuan
(integer) 1
127.0.0.1:6379> GEOADD Chine:city 113.280637 23.125178 guangzhou 121.472644 31.231706 shanghai
(integer) 2

geopos

获取当前定位,一定是一个坐标值

127.0.0.1:6379> GEOPOS Chine:city pingyuan  # 获取指定城市的经纬度,可以获取多个
1) 1) "116.43432050943374634"
   2) "37.16632106437197791"
geodist

两地之间的距离!

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

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

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

127.0.0.1:6379> GEODIST Chine:city pingyuan taian km # 平原到泰安的直线距离,单位km
"159.9139"
georadius

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

127.0.0.1:6379> GEORADIUS Chine:city 110 30 1000 km # 获取距离100 30经纬度1000km内的城市
1) "guangzhou"
2) "taian"
3) "pingyuan"
4) "jinan"
127.0.0.1:6379> GEORADIUS Chine:city 110 30 900 km 
1) "guangzhou"										# 显示出距离km
127.0.0.1:6379> GEORADIUS Chine:city 110 30 900 km withdist 
1) 1) "guangzhou"
   2) "831.2636"							    #显示距离km	#显示城市的坐标
127.0.0.1:6379> GEORADIUS Chine:city 110 30 900 km withdist withcoord
1) 1) "guangzhou"
   2) "831.2636"
   3) 1) "113.28063815832138062"
      2) "23.12517743834835215"										# 只显示前三个符合的
127.0.0.1:6379> GEORADIUS Chine:city 110 30 1000 km withdist withcoord count 3
1) 1) "guangzhou"
   2) "831.2636"
   3) 1) "113.28063815832138062"
      2) "23.12517743834835215"
2) 1) "taian"
   2) "902.0122"
   3) 1) "116.80542021989822388"
      2) "35.75990061245884277"
3) 1) "jinan"
   2) "961.4590"
   3) 1) "116.75192087888717651"
      2) "36.5535192727267102"

GEORADIUSBYMEMBER

找出位于指定范围内的元素,中心点是由给定的位置元素决定

127.0.0.1:6379>GEORADIUSBYMEMBER Chine:city pingyuan 1000 km#找出位于指定元素1000km内的元素
1) "taian"
2) "pingyuan"
3) "jinan"
4) "shanghai"
GEOHASH

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

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

# 将二维的经纬度转换为一维的字符串,如果两个字符串越接近,则距离越近
127.0.0.1:6379> GEOHASH Chine:city taian pingyuan
1) "ww753vzhe80"
2) "wwdg3tbvs20"
ZEO底层实现原理(Zset)

其实就是Zset !我么可以使用Zset命令来操作GEO!

127.0.0.1:6379> ZRANGE Chine:city 0 -1 	# 查看地图中全部元素
1) "guangzhou"
2) "shanghai"
3) "taian"
4) "pingyuan"
5) "jinan"
127.0.0.1:6379> ZREM Chine:city shanghai # 移除指定元素
(integer) 1
127.0.0.1:6379> ZRANGE Chine:city 0 -1
1) "guangzhou"
2) "taian"
3) "pingyuan"
4) "jinan"

Hyperloglog(基数统计)

什么是基数?

A{1,3,5,7,8,7} = 5

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

基数(不重复的元素) = 5,可以接受误差

简介:

Redis2.8.9版本更新了Hyperloglog数据结构!

RedisHyperloglog是一个基数统计的算法!

优点:占用的内存是固定,2^64不同的元素的技术,只需要12KB内存,如果要从内存角度来比较的话Hyperloglog首选!

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

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

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

127.0.0.1:6379> PFADD mykey a b c d 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 h g h a s d c m # 创建第二组元素 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) 12

如果允许容错,那就一定可以使用Hyperloglog !

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

Bitmaps

位存储

​ 同级疫情感染人数:感染的用1,没感染的用0

​ 统计用户信息,活跃的和不活跃的!登录的,未登录的!打卡,365打卡!

两个状态的都可以使用Bitmaps

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

​ 365天 = 365 bit 1字节 = 8bit 存储一个人365天的打卡数据,只需要46个字节左右!!!!!

测试实例(打卡)

​ 使用Bitmaps来记录周一到周日的打卡情况

​ 0:未打卡 1:打卡

127.0.0.1:6379> SETBIT sign 0 1  # 第一个数字代表周几,第二个代表是否打卡
(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> SETBIT sign 5 1
(integer) 0
127.0.0.1:6379> SETBIT sign 6 0
(integer) 0

查看某一天是否打卡

127.0.0.1:6379> GETBIT sign 3 # 查看周四是否打卡
(integer) 1
127.0.0.1:6379> GETBIT sign 6
(integer) 0

统计操作,统计打卡的天数!

127.0.0.1:6379> BITCOUNT sign  # 统计这周的打卡记录,就可以看到是否全勤
(integer) 4
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值