一、Geospatial 地理位置
定位,附近的人,打车距离计算,学生请假还假打卡时判断是否在学校中
Redis的geo在3.2就推出了,这个功能可以推算地理位置的信息,两地之间的距离
geoadd 添加地理位置
geoadd key 纬度 经度 名称
# 规则:无法直接添加两极,南极北极,一般正常情况下城市数据是直接录入的
geoadd china:city 116.40 39.90 beijing # china:city是我们的key
geoadd china:city 121.47 31.23 shanghai
geoadd china:city 106.50 29.53 chongqin
geoadd china:city 114.05 22.52 shenzhen
geoadd china:city 120.16 30.24 hangzhou
geoadd china:city 108.96 34.26 xian
geopos 获取城市的地理位置,获取纬度和经度,一定是一个坐标值
geopos china:city beijing chongqin # 可以拿一个也可以多个
geodist 返回两个给定位置之间的距离
geodist china:city beijing shanghai 默认单位是米,返回直线距离
geodist china:city beijing shanghai km 将单位设置为km
georadius 以给定的的经纬度为中心,找到一个半径内的元素
georadius china:city 110 30 500 km # 找110 30这个经纬度为中心,半径500km内的
georadius china:city 110 30 500 km withdist 显示在中心位置的距离
georadius china:city 110 30 500 km withdist withcoord count 1 # 只找一个
比如附近的人这种功能,可以使用这种
georadiusbymember 找出位于指定元素周围的其他元素
georadiusbymember China:city beijing 500km
geo底层实现原理其实就是zset,我们可以使用zset来操作geo
比如我们可以用zset的方法删除某个地理位置
zrange china:city 0 -1
zrem china:city beijing 删除北京
二、Hyperloglog
是一种数据结构,用来做基数统计的算法
优点:占用内存是固定的,2^64个不同的元素的计数(long数据类型的最大值),只需要12kb的内存。官方统计有0.81%的误差率。但是一般情况下我们是可以接受这个误差的。
统计网页的UV(网址的访问量),一个人访问一个网站多次,但是还算一个人的访问。
传统方法用set来保存用户的id,因为set不允许重复。然后统计set中的元素数量。当然在高并发场景下我们允许一定的误差。这个方式保存了大量的用户id,但我们的目的仅仅只是为了计数,这种方案就不太好。
使用hyperloglog
PFadd key1 1 2 3 4 5 # 创建key
pfcount key1 # pfcount统计的就是基数的数量
PFadd key2 4 5 6 7 8
pfcount key2
pfmerge key3 key1 key2 # 合并两组,key3是一个并集
pfcount key3
如果不允许有误差,就使用set或者自己的方法,但是要权衡内存的问题
三、Bitmap
位存储
位图,也是一种数据结构,都是操作二进制来进行记录,只有0或者1的状态。
统计用户信息,比如活跃或者不活跃,登录与未登录,365打卡,等等只有两个状态的情景
比如365天打卡,365天=365bit 1字节=bit 相当于我们只需要45字节左右就可以记录
一个人一年的打卡情况,比如1是打卡,0没有打卡,以下为记录一个人一周的打卡情况
setbit user:1 0 1 # 周一
setbit user:1 1 0 # 周二
setbit user:1 2 1
setbit user:1 3 0
setbit user:1 4 1
setbit user:1 5 1
setbit user:1 6 1
getbit user:1 3 看周四是否打卡
统计打卡天数
bitcount user:1 统计一周打卡几天,之后我们就可以进行判断看是否要扣钱
bitcount user:1 0 4 统计周一到周五打卡天数
四、事务
redis的事务本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务的执行过程中,按照顺序执行。相当于有一个队列,其中有命令1,命令2,命令3.
所以redis的事务有一次性,顺序性,排他性(即单个命令不能被打断)
redis的单条命令是保证原子性的,但是redis的事务不能保证原子性。
redis事务没有隔离级别的概念,所有的命令在事务中,并没有直接被执行,只有发起执行命令的时候才会执行
redis可以实现乐观锁
正常执行事务流程:
multi 开启事务
exec 执行事务
multi
set k1 v1
set k2 v2
get k2
set k3 v3
exec
放弃事务:
multi
set k4 v4
discard
放弃之后其中的代码不会执行
编译型错误:
当运行事务过程中,出现编译型错误时,比如其中某一条命令写错了,那么所有这个事务中的所有命令都不会执行。
当运行时异常:
当出现运行异常,比如出现了逻辑错误(比如1/0这种),那么只能那一条命令失败,其他命令会照常运行,所以redis的事务无法保证原子性。