Redis基本使用

Redis

Redis是单线程:

官方:Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。

Redis为什么单线程还这么快?

首先我们思考两个问题:

1、高性能的服务器一定是多线程的么?

2、多线程一定比单线程效率高么?

原因:

1.Redis是基于内存的,内存的读写速度非常快

2.Redis是单线程的,省去了多线程CPU上下文切换线程的时间;

3.Redis使用多路复用技术,可以处理并发的连接。非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。

五大数据类型

RedisKey

[root@localhost bin]# redis-server qconfig/redis.conf 
15883:C 13 May 2020 22:57:17.381 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
15883:C 13 May 2020 22:57:17.381 # Redis version=5.0.8, bits=64, commit=00000000, modified=0, pid=15883, just started
15883:C 13 May 2020 22:57:17.381 # Configuration loaded
[root@localhost bin]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys * #查看所有key
(empty list or set)
127.0.0.1:6379> set name qyh #set key
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> exists name #判断一个key是否存在
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
127.0.0.1:6379> move name 1 #移除当前的key
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name qyh
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> clear
127.0.0.1:6379> get name
"qyh"
127.0.0.1:6379> expire name 10 #设置过期时间,单位是s
(integer) 1
127.0.0.1:6379> ttl name #查看当前key的剩余时间
(integer) 3
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> type name #查看当前key的类型
string
127.0.0.1:6379> type age
string

更多命令可以在https://redis.io/commands官网查看

String(字符串)

###################################################
127.0.0.1:6379> set t1 v1 #设置值
OK
127.0.0.1:6379> get t1 #获得值
"v1"
127.0.0.1:6379> keys * #获得所有key
1) "t1"
127.0.0.1:6379> exists t1 #判断某一个key是否存在
(integer) 1
127.0.0.1:6379> append t1 "hello" #追加字符串,如果当前key不存在set一个
(integer) 7
127.0.0.1:6379> get t1
"v1hello"
127.0.0.1:6379> strlen t1  #获得字符串长度
(integer) 7
127.0.0.1:6379> append t1 ",word!"
(integer) 13
127.0.0.1:6379> strlen t1
(integer) 13
127.0.0.1:6379> get t1
"v1hello,word!"
127.0.0.1:6379> 
###################################################
#i++
#步长 i+=
127.0.0.1:6379> set views 0 #初始浏览量
OK
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> decr views
(integer) 0
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incrby views 10 #可以设置步长,指定增量
(integer) 10
127.0.0.1:6379> decrby views 11 #设置步长,指定减量
(integer) -1
###################################################
#字符串范围 range
127.0.0.1:6379> set key1 "hello,word!" # 设置key1的值
OK
127.0.0.1:6379> get key
(nil)
127.0.0.1:6379> get key1
"hello,word!"
127.0.0.1:6379> getrange key1 0 3 # 截取字符串[0,3]
"hell"
127.0.0.1:6379> getrange key1 0 -1 # 获取全部字符串 和 get key 一致
"hello,word!"
127.0.0.1:6379> 
​
#替换
127.0.0.1:6379> set key2 qwerasd
OK
127.0.0.1:6379> get key2
"qwerasd"
127.0.0.1:6379> setrange key2 1 oo #指定从那个字符串开始替代 替换为什么
(integer) 7
127.0.0.1:6379> get key2
"qoorasd"
127.0.0.1:6379> 
​
###################################################
#setex(set with expire)  #设置过期时间
#setnx(set if not exist) #不存在设置 (在分布式锁中会常常使用)
​
127.0.0.1:6379> setex key3 30 "syh" #设置一个key3 值为syh 30s后过期
OK
127.0.0.1:6379> ttl key3
(integer) 21
127.0.0.1:6379> get key3
"syh"
127.0.0.1:6379> setnx mykey "redis" #如果mykey不存在,创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "key1"
2) "key2"
3) "mykey"
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> setnx mykey "Mysql" #如果存在,创建失败
(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> keys *
1) "k1"
2) "k3"
3) "k2"
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)
​
#对象
set user:1{name:syh,age:19} #设置一个user:1 对象 值为json字符串来保存一个对象!
​
#这里的key是一个巧妙的设计:user:{id}:{filed} ,如此设计在redis中是完全可以的
​
127.0.0.1:6379> mset user:1:name syh user:1:age 19
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "syh"
2) "19"
​
###################################################
​
getset #先get再set
​
127.0.0.1:6379> getset py redis #如果不存在值,返回nil
(nil)
127.0.0.1:6379> get py
"redis"
127.0.0.1:6379> getset py mysql #如果存在值,返回当前值,再set新值
"redis"
127.0.0.1:6379> get py
"mysql"
127.0.0.1:6379> 

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

  • 计数器

  • 统计多单位的数量

  • 粉丝数

  • 对象缓存和存储

List

基本数据类型,列表。在redis里边可以把List作为栈、队列,阻塞队列使用!

所有list命令都以l开头

###################################################
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 rigth #将一个值或多个值,插入我们的列表尾部(右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "rigth"
​
###################################################
LPOP
RPOP
127.0.0.1:6379> lrange list 0 -1 
1) "three"
2) "two"
3) "one"
4) "rigth"
127.0.0.1:6379> Lpop list # 移除list第一个元素
"three"
127.0.0.1:6379> rpop list # 移除list最后一个元素
"rigth"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
​
###################################################
lindex
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 1 #通过下标获取 list 中某一个值!
"one"
127.0.0.1:6379> lindex list 0
"two"
127.0.0.1:6379> 
​
###################################################
llen
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> lpush list four
(integer) 4
127.0.0.1:6379> lpush list ffive
(integer) 5
127.0.0.1:6379> llen list #返回list长度
(integer) 5
​
###################################################
移除指定值!
lrem
​
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "ffive"
3) "four"
4) "three"
5) "two"
6) "one"
127.0.0.1:6379> lrem list 1 ffive #移除list集合中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "four"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379> lrem list 1 three
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lpush list three
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "four"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "two"
3) "one"
127.0.0.1:6379> 
​
###################################################
trim 修剪:list 截断!
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist ",word"
(integer) 2
127.0.0.1:6379> rpush mylist "wellcome"
(integer) 3
127.0.0.1:6379> rpush mylist " to here"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2 #截取指定的长度!
OK
127.0.0.1:6379> lrange mylist 0 -1
1) ",word"
2) "wellcome"
​
###################################################
rpoplpush # 移除列表的最后一个元素,并将该元素移动到新的列表中
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 "hello12"
(integer) 3
127.0.0.1:6379> rpoplpush mylist mylist2 # 移除列表的最后一个元素,并将该元素移动到新的列表中
"hello12"
127.0.0.1:6379> lrange mylist 0 -1 #查看原来的列表
1) "hello"
2) "hello1"
127.0.0.1:6379> lrange mylist2 0 -1 #查看列表中,确定存在该值
1) "hello12"
127.0.0.1:6379> 
​
###################################################
lset 将列表中指定下标的值替换为另外一个值,相当于更新
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 v1 
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "v1"
127.0.0.1:6379> lset list 0 item #如果存在,更新当前下标值
OK
127.0.0.1:6379> lrange list 0 -1
1) "item"
127.0.0.1:6379> lset list 1 v2 #如果不存在改下标,报错
(error) ERR index out of range
​
###################################################
linsert #将某个具体的value插入到列表中某个元素的前面或者后面
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist ",word!"
(integer) 2
127.0.0.1:6379> linsert mylist before ",word!" "qyh"
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "qyh"
3) ",word!"
127.0.0.1:6379> linsert mylist after ",word!" "syh"
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "qyh"
3) ",word!"
4) "syh"
127.0.0.1:6379> 
​

小结

  • 它实际上是一个链表,before Node after,left,right都可以插入值

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

  • 如果key存在,新增内容

  • 如果移除了所有的值,空链表,也代表不存在!

  • 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点。

应用场景:

  • 消息队列 (lpush,rpop),栈(lpush,lpop)!

Set(集合)

set中的值是不能重复的!

###################################################
127.0.0.1:6379> sadd myset hello # set集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset qyh
(integer) 1
127.0.0.1:6379> sadd myset word
(integer) 1
127.0.0.1:6379> smembers myset # 查看指定set的所有值
1) "qyh"
2) "hello"
3) "word"
127.0.0.1:6379> sismember myset hello # 判断某一个值是否在set集合中
(integer) 1
127.0.0.1:6379> sismember myset v1
(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
(integer) 2
127.0.0.1:6379> smembers myset
1) "qyh"
2) "word"
​
###################################################
set 无序不重复集合。抽随机!
​
127.0.0.1:6379> srandmember myset #随机抽选一个元素
"qyh"
127.0.0.1:6379> srandmember myset
"word"
127.0.0.1:6379> srandmember myset
"word"
127.0.0.1:6379> srandmember myset
"word"
127.0.0.1:6379> srandmember myset
"word"
127.0.0.1:6379> srandmember myset
"qyh"
127.0.0.1:6379> srandmember myset 2 #随机抽选指定个数的元素
1) "qyh"
2) "word"
​
###################################################
删除指定的key,随机删除key!
127.0.0.1:6379> SMEMBERS myset
1) "beautiful"
2) "qyh"
3) "word"
127.0.0.1:6379> spop myset #随机移除元素
"qyh"
127.0.0.1:6379> spop myset
"beautiful" 
127.0.0.1:6379> SMEMBERS myset
1) "word"
​
###################################################
将一个指定的值,移动到另外一个set集合中!
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset word
(integer) 1
127.0.0.1:6379> sadd myset qyh
(integer) 1
127.0.0.1:6379> sadd myset2 t2
(integer) 1
127.0.0.1:6379> smove myset myset2 qyh #将指定的元素移动到另外一个set集合中
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "word"
127.0.0.1:6379> SMEMBERS myset2
1) "t2"
2) "qyh"
​
###################################################
实现并集,如共同好友之类的
数字类集合:
 -差集
 -交集
 -并集
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  # 差集
1) "b"
2) "a"
127.0.0.1:6379> SINTER key1 key2 # 交集
1) "c"
127.0.0.1:6379> SUNION key1 key2 # 并集
1) "c"
2) "b"
3) "e"
4) "a"
5) "d"
共同关注,推荐好友之类的!

Hash

map集合,key-Map集合(key-<key-value>),value 是一个map集合 !本质和String类型没有太大区别,还是一个简单的key-value!

127.0.0.1:6379> hset myhash field1 qyh # set一个具体的key-value
(integer) 1
127.0.0.1:6379> hget myhash field1  # 获取一个字段值
"qyh"
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 #删除hash指定的key字段,对应的value也就没了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
​
###################################################
hlen
127.0.0.1:6379> hmset myhash field1 hello field2 world field3 qyh
OK
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
3) "field1"
4) "hello"
5) "field3"
6) "qyh"
127.0.0.1:6379> hlen myhash # 获取hash表的字段数量
(integer) 3
###################################################
127.0.0.1:6379> hexists myhash field1 # 判断hash中指定的字段是否存在
(integer) 1
127.0.0.1:6379> hexists myhash field4
(integer) 0
127.0.0.1:6379> 
​
###################################################
# 只获得所有的field
# 只获得所有的value
127.0.0.1:6379> hkeys myhash # 只获得所有的field
1) "field2"
2) "field1"
3) "field3" 
127.0.0.1:6379> hvals myhash # 只获得所有的value
1) "world"
2) "hello"
3) "qyh"
​
###################################################
incr decr
127.0.0.1:6379> hset myhash field4 3 
(integer) 1
127.0.0.1:6379> HINCRBY myhash field4 1 # 指定一个增量
(integer) 4
127.0.0.1:6379> HINCRBY myhash field4 -1
(integer) 3
127.0.0.1:6379> hsetnx myhash field5 www # 如果不存在,则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field5 xxx # 如果存在,则不可以设置
(integer) 0
​

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

 

Zset(有序集合)

在set基础上,增加了一个值,set k1 v1, zset 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"
​
###################################################
ZRANGEBYSCORE key min max
排序如何实现
127.0.0.1:6379> zadd salary 2500 xiaoming # 添加三个用户
(integer) 1
127.0.0.1:6379> zadd salary 3100 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 300 qyh
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf # 显示全部用户,从小到大排序
1) "qyh"
2) "xiaoming"
3) "zhangsan"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores #显示全部的用户并且附带成绩 从小到大
1) "qyh"
2) "300"
3) "xiaoming"
4) "2500"
5) "zhangsan"
6) "3100"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores #显示工资小于2500员工的升序排列 -inf 无穷小 +inf 无穷大
1) "qyh"
2) "300"
3) "xiaoming"
4) "2500"
127.0.0.1:6379> ZREVRANGE salary 0 -1 # 显示全部用户,从大到小排序
1) "zhangsan"
2) "qyh"
127.0.0.1:6379> ZREVRANGE salary 0 -1 withscores #显示全部的用户并且附带成绩,从大到小
1) "zhangsan"
2) "3100"
3) "qyh"
4) "300
###################################################
# 移除rem中的元素
​
127.0.0.1:6379> zrange salary 0 -1
1) "qyh"
2) "xiaoming"
3) "zhangsan"
127.0.0.1:6379> zrem salary xiaoming # 移除有序集合的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "qyh"
2) "zhangsan"
127.0.0.1:6379> zcard salary # 获取有序集合中的个数
(integer) 2
​
###################################################
127.0.0.1:6379> zadd myset 1 hello
(integer) 1
127.0.0.1:6379> zadd myset 2 world 3 qyh
(integer) 2
127.0.0.1:6379> zcount myset 1 3 # 获取指定区间的成员数量
(integer) 3
127.0.0.1:6379> zcount myset 1 2
(integer) 2
127.0.0.1:6379> 
​

剩下的去官网看文档!

应用场景:

  • 排行榜

  • 带权的信息

  • 排序表

三种特殊数据类型

Geospatial(地理位置)

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

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

只有六个命令

  • geoadd

  • geodist

  • geohash

  • geopos

  • georadius

  • georadiusbymember

geoadd

#geoadd 添加地理位置
#规则:地球两极是无法直接添加。
#有效的经度介于 -180 度至 180 度之间。
#有效的纬度介于 -85.05112878 度至 85.05112878 度之间。
#127.0.0.1:6379> geoadd china:city 39.90 116.40 beijing
(error) ERR invalid longitude,latitude pair 39.900000,116.400000
#参数 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 104.06 30.65 chengdu
(integer) 1
127.0.0.1:6379> geoadd china:city 104.63 28.76 yibin
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqin 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
​
​

geopos

获得当前定位:一定是一个坐标值!

127.0.0.1:6379> geopos china:city beijing # 获取指定城市的经度和纬度!
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
127.0.0.1:6379> geopos china:city beijing xian chengdu
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "108.96000176668167114"
   2) "34.25999964418929977"
3) 1) "104.05999749898910522"
   2) "30.6499990746355806"

geodist

两人之间的距离!

单位:

  • m 表示单位为米。

  • km 表示单位为千米。

  • mi 表示单位为英里。

  • ft 表示单位为英尺。

127.0.0.1:6379> geodist china:city xian chengdu
"610349.9718"
127.0.0.1:6379> geodist china:city xian chengdu km #查看西安到成都的直线距离
"610.3500"
127.0.0.1:6379> geodist china:city chongqin chengdu
"265806.1680"
127.0.0.1:6379> geodist china:city chongqin chengdu km #查看重庆到成都的直线距离
"265.8062"
​

georadius 以给定的经纬度为中心, 找出某一半径内的元素

我附近的人?(获得附近所有人的地址,定位!)通过半径来查询!

获得指定数量的人

所有的数据都应该录入到china:city里边

127.0.0.1:6379> georadius china:city 110 30 1000 km #获取以110 30这个经纬度为圆心,半径为1000km的圆内的城市
1) "yibin"
2) "chengdu"
3) "chongqin"
4) "xian"
5) "shengzhen"
6) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 500 km
1) "chongqin"
2) "xian"
127.0.0.1:6379> georadius china:city 110 30 500 km withdist #显示到圆心位置的距离
1) 1) "chongqin"
   2) "341.9374"
2) 1) "xian"
   2) "483.8340"
127.0.0.1:6379> georadius china:city 110 30 500 km withcoord #显示他人的地理位置信息
1) 1) "chongqin"
   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 withdist withcoord count 1  # 筛选出指定数量的结果
1) 1) "chongqin"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"
​

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

# 找出位于指定元素周围其他的元素!
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city chengdu 700 km
1) "yibin"
2) "chengdu"
3) "chongqin"
4) "xian"

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

该命令将返回11个字符的Geohash字符串,所以没有精度Geohash,损失相比,使用内部52位表示

# 将二维的经纬度转换为了一维的字符串,两个字符串越接近表示两个城市越近
127.0.0.1:6379> geohash china:city beijing chongqin
1) "wx4fbxxfke0"
2) "wm5xzrybty0"

geo底层实现原理其实就是Zset!所以我们可以使用Zset命令操作geo

127.0.0.1:6379> zrange china:city 0 -1 # 查看地图中全部的元素
1) "yibin"
2) "chengdu"
3) "chongqin"
4) "xian"
5) "shengzhen"
6) "hangzhou"
7) "shanghai"
8) "beijing"
127.0.0.1:6379> zrem china:city yibin # 移除指定的元素
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chengdu"
2) "chongqin"
3) "xian"
4) "shengzhen"
5) "hangzhou"
6) "shanghai"
7) "beijing"
​

Hyperloglog

什么是基数

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

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

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

简介

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

Redis Hyperloglog 基数统计算法!、

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

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

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

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

0.81%错误率!统计UV任务,忽略不计!

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 z x v f b # 创建第二组元素 mykey2
(integer) 1
127.0.0.1:6379> PFCOUNT mykey2
(integer) 7
127.0.0.1:6379> PFMERGE mykey3 mykey mykey2 # 合并两组 mykey mykey2=>mykey3 并集
OK
127.0.0.1:6379> PFCOUNT mykey3 #查看并集
(integer) 13

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

如果不允许容错,就使用set或者自己的数据集

Bitmap

位存储

统计用户信息,活跃,不活跃!登录,未登录!打卡!两个状态的都可以使用Bitmap!

Bitmap位图,数据结构!都是操作二进制位来进行记录,就只有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 0
(integer) 0
127.0.0.1:6379> setbit sign 6 1
(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

===========================================================================================

该笔记是随B站up主狂神说视频写的,希望在学习的小伙伴多多去关注该up,讲的很好且不收费!!

https://space.bilibili.com/95256449/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis中,常用的基本数据类型包括字符串(string)、哈希(hash)、列表(list)、集合(set)和有序集合(sorted set)。Redis本身是一个Map,所有数据都采用key:value的形式存储,而key永远是字符串类型。对于字符串类型,value可以是字符串、整型或浮点型,Redis能够自动识别。除了字符串类型,还有哈希类型,可以存储键值对的集合,对于哈希类型的操作,可以使用HSET、HGET等命令。此外,还有列表类型,用于存储有序的字符串列表,可以使用LPUSH、RPUSH等命令进行操作;集合类型,用于存储不重复的字符串集合,可以使用SADD、SREM等命令进行操作;有序集合类型,用于存储带有权重的有序字符串集合,可以使用ZADD、ZRANGE等命令进行操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Redis的五种常用数据类型的基本使用](https://blog.csdn.net/weixin_43795939/article/details/107815058)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Redis五大基础数据类型的操作](https://blog.csdn.net/weixin_44183721/article/details/126116049)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值