Redis-三种数据结构与事务

一、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的事务无法保证原子性。

posted @ 2020-12-02 19:43  王寄鱼  阅读(141)  评论(0编辑  收藏  举报