1.NoSQL介绍
1.1 什么是NoSQL
-
非关系型数据库就是NoSQL,关系型数据库代表MySQL。
-
对于关系行数据库,是需要把数据存储到库、表、行、字段里,查询的时候根据条件一行一行地去匹配,当量非常大的时候就很耗费时间和资源,尤其是数据是需要从磁盘里去检索 (如图)。
-
NoSQL数据库存储原理非常简单(典型的数据类型为k-v),不存在繁杂的关系链,比如mysql查询的时候,需要找到对应的库、表(通常是多个表)以及字段。
-
NoSQL数据可以存储在内存里,查询速度非常快。
-
NoSQL在性能表现上虽然能优于关系型数据库,但是它并不能完全替代关系型数据库。
-
NoSQL因为没有复杂的数据结构,扩展非常容易,支持分布式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lhRwZ9KP-1650532184594)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220420192317386.png)]
1.2 常见NoSQL数据库
-
键值数据库:redis、memcached适合储存用户信息,应用场景比如内存缓存,会话、配置文件、参数、购物车等等。往往是频繁读写、拥有简单数据模型k-v形式的的应用。其优点:扩展性好,灵活,大量操作性能高。缺点:数据无结构化,只能当作字符串或者二进制数据,通常只能通过键值来查询。
-
文档数据库:mongodb将数据以文档的形式储存。应用场景比如Web应用,存储面向文档或者类似半结构化的数据,<key,value> value是JSON结构的文档。 其优点:结构灵活,可以根据value构建索引。**其缺点:**缺乏统一查询语法。
-
列簇数据库:HBase等,应用场景分布式数据存储与管理,以列簇式存储,将统一列数据存储在一起。其优点:是可扩展性强,查找快,复杂性低。缺点:是功能局限,不支持事务的一致性。
-
图形数据库:Neo4J、Infinite Graph、OrientDB,应用场景为社交网络,推荐系统,其多为图结构。优点:是支持复杂的语法,其缺点:是复杂性高,只能支持一定的数据规模。
由图可知,当业务场景越来越复杂的时候,仅仅是mysql是满足不了我们的需求的,所以我们需要学习nosql。
1.3 总结
- 关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,让NoSQL数据库对关系型数据库的不足进行弥补。
- 一般会将数据存储在关系型数据库中,在nosql数据库中备份存储关系型数据库的数据。
2.Redis入门以及环境搭建
2.1 概述
Redis是什么?
Redis(Remote Dictionary Server ),即远程字典服务。
它是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
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能该干什么?
- 内存存储、持久化,内存是断电即失的,所以需要持久化(RDB、AOF)
- 高效率、用于高速缓冲
- 发布订阅系统
- 地图信息分析
- 计时器、计数器(eg:浏览量,评论数,点赞数等)
- 分布式数据共享,如分布式集群架构中的session分离
- 消息队列
- 分布式锁
Redis的特性
- 多样的数据类型
- 持久化
- 集群
- 事务
2.2 Redis环境搭建
官网:https://redis.io/
中文网:http://www.redis.cn/
注意:Windows版本的Redis已经很久没更新了,更多的还是使用Linux服务器使用Redis。
2.2.1 Windows系统下安装
下载地址:https://github.com/dmajkic/redis
-
解压安装包
* redis.windows.conf:配置文件* redis-cli.exe:redis的客户端* redis-server.exe:redis服务器端
-
双击redis-server.exe
-
启动redis-cli.exe测试 输入如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LHdsE52l-1650532184595)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220420201057275.png)]
2.2.2 Linux下配置Redis
注意 这里我们使用centos7系统 (可以使用Unbantu,但不建议使用centos6或8) 如何购买和使用阿里云服务器、腾讯云服务器和虚拟服务器请参考csdn
- 到redis官网下载安装包! redis-6.0.8.tar.gz 通过xftp工具上传至/opt目录下(或者data目录下)
当然也可以通过命令的方式下载
wget https://download.redis.io/releases/redis-6.2.6.tar.gz
- 通过xshell解压Redis的安装包 (注意:如果没有使用共xshell和xftp的同学请自行百度,很容易上手)
在opt/目录下
tar -zxvf redis-6.2.6.tar.gz
安装redis 6需要相匹配版本的gcc(必须是gcc 5.0以上)我这里版本就不匹配,需要重新下载gcc与gcc-c++。
gcc -v
# 安装scl (进入刚解压的文件夹内/opt/redis-6.2.6 cd redis-6.2.6)
$ yum -y install centos-release-scl
# 升级gcc到9版本
$ yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
# 长期使用gcc 9版本的话,将执行命令输入到环境变量配置
$ echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
# 编译安装redis,存放在local目录下
$ make PREFIX=/local/redis-6.2.6
$ make install
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wxkejtW4-1650532184595)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220420231809090.png)]
现在我们进入安装好的文件夹内(/local/redis-6.2.6/bin)
执行命令,出现下图说明安装成功!
redis-server
ctrl+c 返回命令行
注意:为了让其能够在后台自动启动,我们将之前解压的文件夹中的redis.conf复制到当前目录
mkdir myconfig
cp /opt/redis-6.2.6/redis.conf myconfig
cd myconfig
修改redis.conf
vim redis.conf
使用 i 进行插入数据
daemonize yes (能让服务端一直开启)
并注释掉#bind 127.0.0.1 -::1这一行,使其能够被外部访问
先esc 后 :wq 返回命令行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fdnBJPzL-1650532184596)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220420233342824.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xS5LyWzz-1650532184596)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220420233400424.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X1sgg6kI-1650532184596)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220420234753598.png)]
执行ps -ef|grep redis命令,找到已启动的redis服务,使用kill命令杀掉redis服务进程。
ps -ef|grep redis 查看redis进程
kill -9 3763 (表示进程号)
redis-server myconfig/redis.conf
再另一个窗口进行交互
关闭服务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O3x4h1kg-1650532184596)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421001903616.png)]
到这里就已经大功告成了!~!
2.3 测试性能
redis-benchmark Redis官方提供的性能测试工具,参数选项如下:
redis-benchmark [-h ] [-p ] [-c ] [-n ] [-k ]
序号 | 选项 | 描述 | 默认值 |
---|---|---|---|
1 | -h | 指定服务器主机名 | (默认 127.0.0.1) |
2 | -p | 指定服务器端口 | (默认 6379) |
3 | -s | 指定服务器 socket | |
4 | -a | Redis 认证密码 | |
5 | -c | 指定并发连接数 | (默认 50) |
6 | -n | 指定请求数 | (默认 100000) |
7 | -d | 以字节的形式指定 SET/GET 值的数据大小 | (默认 2) |
8 | –dbnum | 选择指定的数据库号 | (默认 0) |
9 | -k | 1=keep alive 0=reconnect | (默认 1) |
10 | -r | SET/GET/INCR 使用随机 key, SADD 使用随机值 | |
11 | -P | 通过管道传输 请求 (no pipeline) | |
12 | -q | 退出,仅显示 query/sec 值 | |
13 | –csv | 以 CSV 格式输出 | |
14 | -l | 生成循环,永久执行测试 | |
15 | -t | 仅运行以逗号分隔的测试命令列表 | |
16 | -I | Idle 模式,仅打开 N 个 idle 连接并等待 |
2.3.1 简单测试
# 测试:100个并发连接 100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
一个窗口开启服务器
另一个窗口进行测试
3. Redis基础知识
3.1 Redis基本操作
1.切换数据库(redis默认有16个数据库,默认使用的是第0个)
select index 进行切换数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-axzffVz7-1650532184597)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421103837103.png)]
2.查看数据库大小
dbsize
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GOWQ1vrS-1650532184597)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421104003099.png)]
3.清空当前数据库(3号数据库)
flushdb
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Or6IoSRN-1650532184597)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421104116967.png)]
4.清空所有数据库
flushall
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0QgWhFj9-1650532184598)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421104313649.png)]
3.2 Redis是单线程的
redsi很快,redis基于内存操作,cpu不是redis性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程。redis是c语言写的,官方数据是100000+的QPS。
redis为什么单线程还这么快
1.误区:高性能的服务器一定是多线程的?
2.误区二:多线程一定比单线程高!
核心:redis将所有数据全部放在内存中,所以说使用单线程去操作效率高,多线程(cpu上下文切换:耗时操作),对于内存系统来说,如果没有上下文切换效率是最高的,多次读写都是在一个cpu上的,在内存情况下,这个就是最佳方案!
4.Redis命令操作
4.1 key通用命令
下列操作,以string类型为演示(其它基本类型也适用)
1.查找所有的键
keys *
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UIITDYl1-1650532184598)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421110030947.png)]
2.判断键是否存在
exists key (键名)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-39tk0gtx-1650532184598)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421110213309.png)]
3.获取键对应的值
get key
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w9NIVyDh-1650532184598)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421110550332.png)]
4.设置键过期时间
expire key 10 (设置该键10秒钟之后过期)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fxsUgogT-1650532184599)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421110645073.png)]
5.查看键值剩余过期时间 (-2表示已经过期)
ttl key
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-emNFKV6R-1650532184604)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421110731287.png)]
再使用get age就会返回空了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hg8pVEHp-1650532184605)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421110826519.png)]
Redis的key,通过TTL命令返回key的过期时间,一般来说有3种:
- 当前key没有设置过期时间,所以会返回-1.
- 当前key有设置过期时间,而且key已经过期,所以会返回-2.
- 当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.
6.对key重命名
rename key newkey
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LyG5w9qQ-1650532184605)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421111525331.png)]
7.删除key
del key
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQnxFJ2A-1650532184605)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421112219405.png)]
8.设置键值
set key value
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y5pVxMPS-1650532184606)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421112542303.png)]
9.获取键对应value的类型
type key
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hQSPWbTV-1650532184606)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421145223914.png)]
更多命令的学习去,请查看:https://www.redis.net.cn/order/
4.2 redis五大基本数据类型
4.2.1 概述
redis的数据结构:
-
redis存储的是:key,value格式的数据,其中key都是字符串,value有5种不同的数据结构
-
value的数据结构:
- 字符串类型 : string
- 哈希类型 hash : map格式
- 列表类型 list : linkedlist格式。支持重复元素
- 集合类型 set : 不允许重复元素
- 有序集合类型 sortedset:不允许重复元素,且元素有顺序
- 上面这五种是基本的数据类型。
4.2.2 字符串类型 string
1. 存储: set key value
2. 获取: get key
3. 删除: del key
4. 追加: append key value
5. 判长: strlen key
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PcDUbAm7-1650532184606)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421115729865.png)]
案例一 浏览量变化
set views 0
get views
incr views #浏览量自增 1
get views
decr views #自减 1
get views
incrby views 10 #设置自增步长为10
decrby views 10 #设置自减步长为10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-un8GiyFc-1650532184606)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421120415963.png)]
案例二: 字符串范围 range
set message "hello,world"
get message
getrange message 0 3 # 截取字符串 [0,3]
getrange message 0 -1 # 获取全部的字符串 和 get message是一样的
setrange message 6 error # 替换指定位置开始的字符串!
get message
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2xXkQaa-1650532184606)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421121513717.png)]
案例三: 过期时间设置
# setex (set with expire) # 设置过期时间
# setnx (set if not exist) # 不存在在设置 (在分布式锁中会常常使用!)setex key 30 "hello" # 设置key3 的值为 hello,30秒后过期
ttl key
get key
setnx mykey "redis" #如果mykey不存在,则创建 如果存在,则失败!
keys *
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M3mYSCKV-1650532184607)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421123846481.png)]
案例四:同时设置或修改多值
mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
keys *
mget k1 k2 k3 # 同时获取多个值
msetnx k1 v1 k4 v4 # msetnx 是一个原子性的操作,要么一起成功,要么一起失败!
get k4
set user:1 {name:zhangsan,age:3} # 设置一个user:1 对象 值为 json字符来保存一个对象!
# 这里的key是一个巧妙的设计: user:{id}:{filed} , 如此设计在Redis中是完全OK了!
mset user:1:name zhangsan user:1:age 2
mget user:1:name user:1:age
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6eysE4Bv-1650532184607)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421124723686.png)]
案例五:先获得再设置修改
getset db redis # 如果不存在值,则返回 nil
get db
getset db mongodb # 如果存在值,获取原来的值,并设置新的值
get db
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vfhc1gUk-1650532184607)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421124812412.png)]
String的使用场景:计数器(value为数字),统计多个单位的数量,粉丝数,浏览数,对象缓存存储等!
4.2.3 List(列表)
在redis里面,我们可以把list玩成 ,栈、队列、阻塞队列!
注意:所有的list命令都是用l开头的,Redis不区分大小命令。
1.增加数据
lpush mylist one # 将一个值或者多个值,插入到列表头部 (左)
lpush mylist two
lpush mylist three
lrange mylist 0 -1 #获取mylist所有的值
rpush mylist four # 将一个值或者多个值,插入到列表位部 (右)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wEOK8VMC-1650532184607)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421131725015.png)]
2.删除数据
lrange mylist 0 -1
lpop mylist # 移除list的第一个元素
rpop mylist # 移除list的最后一个元素
lrange mylist 0 -1
lrem mylist 1 one # 移除list集合中指定个数的value,精确匹配
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HmDYmJDq-1650532184607)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421132458875.png)]
3.查找数据
lindex mylist 0 # 通过下标获得 list 中的某一个值!
lpush mylist one
llen mylist #获取列表的长度
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-87bfp6q9-1650532184608)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421132756167.png)]
4.其它命令
trim 修剪
rpoplpush # 移除列表的最后一个元素,将他移动到新的列表中!
lset #将列表中指定下标的值替换为另外一个值,更新操作
linsert # 将某个具体的value插入到列把你中某个元素的前面或者后面!ltrim mylist 1 2 # 通过下标截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素!
rpoplpush mylist myotherlist
lset mylist 0 zero # 如果不存在列表,更新就会报错 (将下标为0的元素替换为zero)
linsert mylist before "zero" "zero1"
linsert mylist after "two" "tree"
小结
- 他实际上是一个双向链表,before Node after , left,right 都可以插入值
- 如果key 不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在!
- 在两边插入或者改动值,效率最高! 中间元素,相对来说效率会低一点~
消息排队!消息队列 (Lpush Rpop), 栈( Lpush Lpop)!
4.2.4 Set(集合)
set值是不能重复的
常见操作
1. 存储:sadd key value
sadd myset a
2. 获取:smembers key #获取set集合中所有元素
smembers myset
3. 判断:sismember myset a #判断某一值是否存在
4. 判长:scard myset #判断myset有多少元素
3. 删除:srem key value #删除set集合中的某个元素
srem myset a
4. 随机抽取:srandmembers myset #随机抽取一个元素
5. 随机抽取若干:srandmembers myset x #随机抽取x个元素
6. 随机删除: spop myset #随机删除set集合中的元素
7. 移动元素:smove myset myset2 "dx" # 将一个指定的值,移动到另外一个set集
数字集合:
8. sdiff key1 key2 #求差集
9. sinter key1 key2 #求交集
10.sunion key1 key2 #求并集
小结
常见案例:微博,A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中!共同关注,共同爱好,二度好友,推荐好友!(六度分割理论)
4.2.5 Hash(哈希)
Map集合,key-map! 时候这个值是一个map集合! 本质和String类型没有太大区别,还是一个简单的key-vlaue!
常见操作
1. 存储: hset key field value
2. 获取: * hget key field: 获取指定的field对应的值* hgetall key:获取所有的field和value
3. 删除: hdel key field
4. 设置:* hmset myhash field1 hello field2 world # set多个 key-vlaue* hset myhash field1 hello1 #设置一个字段的value* hsetnx myhash field4 hello # 如果不存在则可以设置
5. 获取字段操作:* hlen myhash # 获取hash表的字段数量!* hexists myhash field1 # 判断hash中指定字段是否存在!* hkeys myhash # 只获得所有field* hvals myhash # 只获得所有value
(incr decr)* hset myhash field3 5 #指定增量!* hincrby myhash field3 1 #字段的值增加1
小结
hash变更的数据 user name age,尤其是是用户信息之类的,经常变动的信息! hash 更适合于对象的存储,String更加适合字符串存储!
4.2.6 Zset(有序集合)
有序集合类型 sortedset:不允许重复元素,且元素有顺序.每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
常见操作
1. 存储:zadd key score value
2. 获取:zrange key start end [withscores]
3. 删除:zrem key value
4. 排序:zrangebyscore key min max*zrangebyscore key -inf +inf # 显示全部的用户 从小到大!*zrevrange salary 0 -1 # 从大到进行排序*zrangebyscore key -inf +inf withscores# 显示全部的用户 从小到大,并带上成绩!
5. 获取指定区间的数量:zcount key min max# 获取指定区间的成员数量!
其与的一些API,通过我们的学习吗,你们剩下的如果工作中有需要,这个时候你可以去查查看官方文档!
案例思路:set 排序 存储班级成绩表,工资表排序!
普通消息,1, 重要消息 2,带权重进行判断!
排行榜应用实现,取Top N 测试!
4.3 三种特殊数据类型
4.3.1 Geospatial 地理位置
朋友的定位,附近的人,打车距离该如何计算?
Redis 的 Geo 在Redis3.2 版本就推出了! 这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人!
可以查询一些测试数据:http://www.jsons.cn/lngcodeinfo/0706D99C19A781A3/
API:
1.geoadd 将指定的地理空间位置(经度、纬度、名称)添加到指定的key中
2.geopos 从key里返回所有给定位置元素的位置(经度和纬度)
3.geodist 返回两个给定位置之间的距离
4.Geohash 返回一个或多个位置元素的 Geohash 表示
5.Georadius 以给定的经纬度为中心, 找出某一半径内的元素
6.Georadiusbymember 找出位于指定范围内的元素,中心点是由给定的位置元素决定
官方文档:https://www.redis.net.cn/order/3685.html
getadd
# 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
# 参数 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
getpos
获得当前定位:一定是一个坐标值!
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 chongqi
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
GEODIST
两人之间的距离!
单位:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
127.0.0.1:6379> GEODIST china:city beijing shanghai km # 查看上海到北京的直线距离
"1067.3788"
127.0.0.1:6379> GEODIST china:city beijing chongqi km # 查看重庆到北京的直线距离
"1464.0708"
georadius 以给定的经纬度为中心, 找出某一半径内的元素
我附近的人? (获得所有附近的人的地址,定位!)通过半径来查询!
获得指定数量的人,200
所有数据应该都录入:china:city ,才会让结果更加请求!
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km # 以110,30 这个经纬度为中心,寻
找方圆1000km内的城市
1) "chongqi"
2) "xian"
3) "shengzhen"
4) "hangzhou"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km
1) "chongqi"
2) "xian"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist # 显示到中间距离的位置
1) 1) "chongqi"
2) "341.9374"
2) 1) "xian"
2) "483.8340"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord # 显示他人的定位信息
1) 1) "chongqi"
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) "chongqi"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 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"
GEORADIUSBYMEMBER
# 找出位于指定元素周围的其他元素!
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 400 km
1) "hangzhou"
2) "shanghai"
GEOHASH 命令 - 返回一个或多个位置元素的 Geohash 表示
该命令将返回11个字符的Geohash字符串
# 将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近!
127.0.0.1:6379> geohash china:city beijing chongqi
1) "wx4fbxxfke0"
2) "wm5xzrybty0"
GEO 底层的实现原理其实就是 Zset!我们可以使用Zset命令来操作geo!
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"
4.3.2 Hyperloglog
什么是基数?
A {1,3,5,7,8,7}
B{1,3,5,7,8}
基数(不重复的元素) = 5,可以接受误差!
简介
Redis 2.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 c v b n 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) 15
如果允许容错,那么一定可以使用 Hyperloglog !
如果不允许容错,就使用 set 或者自己的数据类型即可!
4.3.3 Bitmap
这些在生活中或者开发中,都有十分多的应用场景,学习了,就是就是多一个思路!
位存储
统计用户信息,活跃,不活跃! 登录 、 未登录! 打卡,365打卡! 两个状态的,都可以使用
Bitmaps!
Bitmap 位图,数据结构! 都是操作二进制位来进行记录,就只有0 和 1 两个状态!
365 天 = 365 bit 1字节 = 8bit 46 个字节左右! 极大了减少存储。
使用bitmap 来记录 周一到周日的打卡
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w2KD5Ex5-1650532184608)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20220421170629813.png)]
查看某一天是否有打卡!
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) 3