一、Geospatial
1.简介
基于位置信息服务
(Location-Based Service,LBS)
的应用。
Redis3.2
版本后增加了对
GEO
类型的支持。主要来维护元素的经纬度。redis
基于这种类型,提供了经纬度设置、查询、范围查询、距离查询、经纬度hash等一些相关操作。
2.GEO底层结构
- 1.约车系统,针对每一辆车,有一个唯一编号,车辆有行驶的经纬度
- 2.呼叫车辆,会暴露用户的经纬度,根据经纬度进行范围查找,进行匹配
- 3.把附近车辆找到后,车辆信息获取,将信息反馈给用户
- 第一种方式,可以使用hash来存储,但hash没有排序功能
- 第二种方式,geo底层结束 zset 来实现。需要将经纬度放在一起,生成一个权重的分数,按这个分数进行排序
- GEOHash编码
- 编码的过程:
- 经度-180,180之间,按给定位数做N次二分区操作。
例如,N=5,做5次二分区操作,例如,坐标116.40
对经度进行编码
11010
对纬度进行编码 39.96
10111
经度:11010
纬度:10111
最后合成的编码:1110011101
3.GEO操作指令
- geoadd < key> < longitude>< latitude>< member> [longitude latitude member...]:添加地理位置 (经度 纬度 名称)
- geopos < key>< member>[member...]:获取指定的位置坐标值
- geodist < key>< member1>< member2>:获取两个位置之间的直线距离。单位:m 米 km 千米 ft英尺 mi英里
- georadius < key>< longitude> < latitue> radius [m | km| fm| mi],以经定的经纬度做为中心,找出给定半径内的位置
4.查找附近的人案例
geoadd nearby 116.511023 39.945711 person1 116.508257 39.946735 person2 116.513395
39.948035 person3 116.51415 39.945131 person4 116.508724 39.943194 person5 116.511526
39.943775 person6 116.509802 39.94419 person7 116.512317 39.946928 person8 116.505166
39.946265 person9 116.506316 39.946375 person10
georadius nearby 116.506316 39.946375 500 m desc count 10
二、redis事务操作
1.事务简介
- ACID
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(isolation)
- 持久性(durabiliby)
2.redis事务
- 提供了multi、exec命令来完成
- 第一步,客户端使用multi命令显式地开启事务
- 第二步,客户端把事务中要执行的指令发送给服务器端,例如set 、get 、lpush,这些指令不会立即执行,进入一个队列中
- 第三步,客户端向服务器发送一个命令 exec,来完成事务提交。当服务器端收到这个指令后,实际去执行上一步中的命令队列.
multi
set k1 v1
set k2 v2
set k3 v3
get k1
exec
multi
set k4 v4
set k5 v5
discard //取消
3.Redis的事务处理机制
3.1原子性
- 第一种情况,在执行exec指令前,客户端发送操作命令有误,redis会报错并记录这个错误。此时,还可以继续发送命令操作,在执行exec命令之后,redis拒绝执行所有提交的指令,返回事务失败的结果。(保证了原子性)
multi
set k1 v1
get k1 v1
set k2 v2
exec
整个队列失败
- 第二种情况,向服务器发送指令,其中有指令和操作的数据类型不匹配,放入队列时并没有报错。使用lpop指令操作失败,但get指令成功了。(不能保证原子性)
multi
lpop k1 //失败
get k1 //成功
exec
- 第三种情况,在执行事务的exec指令时,redis实例发生了故障,导致事务执行失败,如果redis开启了aof日志,可能会有一部分指令被记录到AOF日志中,需要使用redis-check-aof 去检查aof文件,将未完成事务操作从aof清除,从而保证原子性
3.2一致性
- 第一种情况,指令进入队列时就报错,整个事务全部被放弃执行,可以保证数据的一致性。
- 第二种情况,进入队列时没有报错,实际执行时报错,有错误的指令不去执行,正确的指令可以正常执行,可以保证数据的一致性
- 第三种情况,exec指令时redis实例发生故障,根据RDB和AOF情况来做判断
- 如果没有开启rdb和aof,数据在重启后没有,是一致的
- 如果使用了rdb方式,rdb不会在事务执行的时候去保存数据,数据库也是一致的
- 使用aof日志,如果事务队列操作记录没有进入aof,可以保证一致性。如果已加入了一部分,使用redis-check-aof清除事务中已完成的操作,保证事务的一致性
3.3隔离性
- 提交exec指令去执行事务,分成exec之前和exec之后两种情况
- 并发操作在exec指令前,要实现隔离性的保证 ,需要使用watch机制,否则不能保证隔离性
- 在事务执行前,相当于有一个监控器,在监控key是否已经被修改过了,如果已修改,则放弃事务执行,避免了事务的隔离性被破坏。如果客户再次执行,此时,没有其他客户端去修改数据,则执行成功。
- 悲观锁:synchronized
- 乐观锁:Atomic原子操作
- 使用unwatch取消watch命令对所有key的监控。
3.4持久性
- redis内存数据库,取决于持久化配置模式
- 不开启rdb和aof,只当作缓存使用,是不能保证持久性
- 使用rdb,如果在一个事务执行后,下一次的rdb快照还未执行前,redis实例发生故障了,不能保证持久性
- 使用aof, 配置选项 everysec、always、no,也不能保证持久性
- 不管redis采用什么配置模式,都不能保证事务的持久性