Redis事务、数据类型

Redis事务

Redis事务的本质是一组命令的集合。在redis中开启事务后,事务中的命令不会立即执行,而是会推送到一个事务队列中,等到事务提交后,会逐步执行此队列的命令,在执行中如果有命令执行错误,此次事务所以命令取消

  • 开启事务,创建队列
multi
  • 执行事务
exec
  • 取消事务
discard

redis在开启事务时,之后执行的所有的操作均会保存到任务队列中。如果执行了exec命令,那么redis将会逐步执行队列的指令,如果执行discard指令,那么就会取消所有

 

 

事务队列中某个命令出现错误:

 watch监视

redis在开启事务时,其实就是创建了一个事务队列,此次事务所执行的所有命令将不会被立即执行,而是等事务执行之后,才会将队列中的命令一一执行。有时候我们希望在执行队列中的指令不允许修改,那么此时就需要加锁

watch key1 [key2……]

如果被监视的值在exec命令之前被修改过了,那么此次事务队列中的命令全部失效

  •  unwatch:取消监视的所有key

tips:执行exec会释放所有被监视的key

Redis的删除策略

我们知道Redis中的数据都是存储在内存中的,内存空间非常宝贵,当我们对不需使用的数据应该立即删除

在redis中,针对过期和删除的数据有三种策略来清除。分别为定时删除、惰性删除、定期删除。

定时删除策略

在设置键的过期时间的同时,Redis内部会创建一个定时器,当key设置有过期时间,时间到达时,执行了del的key,由定时器认为执行对键的删除操作

  • 优点:定时器时间到了就执行删除,能够有效快速释放内存空间,节约内存
  • 缺点:定时器时间到了就执行删除,在这一时刻如果cpu正在处理其他指令,那么cup的负载会一下子变得非常搞,直接影响redis处理请求的响应速度
  • 总结:牺牲cpu性能来释放内存(时间换空间),定时删除策略是对内存清除最有效的方式

惰性删除策略

数据到达过期时间不删除,等下次访问该数据时再删除

  • 优点:有效节约cpu性能,发现必须要删除时才删除
  • 如果数据过期后一直没有访问数据,长时间占用内存使用量,内存压力大
  • 总结:牺牲内存使用量来换取cpu的性能(空间换时间)

定期删除策略

从定时删除和惰性删除策略来看,惰性删除浪费内存容易造成内存溢出,而定时删除影响cpu性能降低redis的响应速度和吞吐量。两种删除方式不管在cpu还是内存上都有些极端。定期删除策略则是一种折中办法

  • 定期删除工作原理:

 周期性轮询redis中数据的有效性,采取智能算法抽取的策略,对过期数据大的进行有效删除

  • 优点:智能根据数据库有效数据占用率来选择删除的力度,并且检测频率(server.hz)可以根据cpu占用率适当调整

redis底层采用的是定期删除+惰性删除策略

hz通过info命令可以查询到,具体位置在info server组下。

三种策略总结

  • 定时删除(对内存清除最有效)
    • 不管cpu当前使用率是否紧张,时间到了立马删除,内存压力小,cpu压力大,采用时间换空间策略
  • 惰性删除(等到二次访问再删除)
    • 等到确切删除的时候再删除,造成内存使用量浪费,cpu压力小,采用空间换时间策略
  • 定期删除(采取智能抽取检查)
    • 周期性删除,随机抽取一部分key删除,如发现占整体key的比例较大,则重新抽取一部分key删除。之后轮询下一个数据、下一台redis

淘汰策略

  • allkeys-lru:在16个数据库(前提你没有修改databases)的所有key中,选择使用次数最少的数据进行淘汰
  • allkeys-lfu:在16个数据库的所有key中,选择最后一次使用离现在最长的数据进行淘汰
  • allkeys-random:在16个数据库的所有key中,随机选择一部分数据进行淘汰
  • volatile-lru:在所有有设置过期时间的key中,选择使用次数最少的数据进行淘汰
  • volatile-lfu:在所有有设置过期时间的key中,选择最后一次使用离现在最长的数据进行淘汰
  • volatile-ttl:在所有有设置过期时间的key中,选择将要过期的数据进行淘汰
  • volatile-random:在所有有设置过期时间的key中,随机选择一部分数据进行淘汰
  • no-envication:放弃淘汰数据,Redis4.0及以上版本默认策略

Redis高级数据类型

BitMaps

Redis在2.2.0 版本之后添加了bitmaps操作,bitmaps事实上并不是一种新的数据类型,而是基于字符串位操作的集合

bitmaps的位操作分成两组:

  • 1)把字符串的某个位设置为1或者0,或者获取某个位上的值
  • 2)对于一组位的操作,对给定的比特范围内,统计设定值为1的数目。

bitmaps最大的优势是在存储数据时可以极大的节省空间

tips:Bitmaps本身不是一种数据结构,他实际上就是一个可以进行位运算的字符串

BitMaps位图原理

假设我们存储了asd字符串在redis当中,a的ASCII为97,对应的为115、100,那么对应的二进制数据图如下:

getbit key offset
  • 说明:获取指定key偏移量位置的二进制值。
  • offset:偏移量

getbit命令示例:

 图解:

setbit key offset value
  • 说明:设置key的指定偏移量上的值
  • offset:索引偏移量(从0开始计算)
  • value:具体的值(只能是0或1)

图解:

 上图能分析,如果偏移量间隔过大,势必会造成中间补0的现象较大

例如:

  • setbit test2 300 1

注意:在第一次setbit时,如果偏移量非常大,那么意味着前面的空出都需要0位来补充,因此会造成redis的阻塞。

bitcount key [start end]
  • 说明:统计指定key的二进制位上的1的个数,不指定start和end就获取全部
  • start:起始索引
  • end:终止索引

bitop operation destkey key [key...]
  • 说明:用于多个BitMap做交集(and)、并集(or)、非(not)、异或(xor)操作,并将其结果计算保存到新的key中
  • operation:操作类型
    • and:交集
    • or:并集
    • not:非
    • xor:异或
  • destkey:存储计算的结果

and

与(&),取交集,有假为假

准备数据:

127.0.0.1:6379> setbit test3 0 1
(integer) 0
127.0.0.1:6379> setbit test3 1 1
(integer) 0
127.0.0.1:6379> setbit test3 2 1
(integer) 0
127.0.0.1:6379> setbit test3 3 0
(integer) 0
127.0.0.1:6379> setbit test4 0 1
(integer) 0
127.0.0.1:6379> setbit test4 1 0
(integer) 0
127.0.0.1:6379> setbit test4 2 1
(integer) 0
127.0.0.1:6379> setbit test4 3 1
(integer) 0

取and操作:

and命令图解:

 

 or

或(|),取并集,按位非操作只能指令一个key,代表对哪个进行"按位非"操作,有真为真

 or命令图解

 not

非(~),按位取反,1为0,0为1,按位取反时如果不够8的整数位后面的均会以0补齐

 

 

 xor

异域(^),相同为0,不同为1

 

 BitMap总结

bitmap存储单位是"位",计算机最小的存储单位都是byte(字节),而一个字节是8个位,因此存储效率明显是bitmap高多了,而实际开发中id往往是Long类型进行存储(8个字节),8*8=64。因此存储效率可想而知,但由于bitmap直接操作的是"位",操作起来不方便,在开发中操作"位"给开发者带来一定的困难,需要花费一定的时间来操作,因此在数据结构的角度上来看,bitmap实质上是采取时间换空间的操作

  • 优点:存储效率高
  • 缺点
    • 操作不便,给开发者带来一定的困难
    • setbit偏移量较高时,需要补零,造成Redis阻塞(在此期间,Redis主线程将会被阻塞)

HyperLogLog

Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

HyperLogLog命令

添加数据:pfadd key val [val ...]

127.0.0.1:6379> pfadd a1 0
(integer) 1
127.0.0.1:6379> pfadd a1 1
(integer) 1
127.0.0.1:6379> pfadd a1 1
(integer) 0
127.0.0.1:6379> pfadd a1 2
(integer) 1
127.0.0.1:6379>

统计数据:每个key同样的val只会统计一次

pfcount key [key ...]

127.0.0.1:6379> pfcount a1
(integer) 3
127.0.0.1:6379>

合并数据:将多个heperloglog合并在一起,同样的key的val只会保留一个

pfmerge destkey sourcekey [sourcekey ....]

127.0.0.1:6379> pfadd a2 0
(integer) 1
127.0.0.1:6379> pfadd a2 1
(integer) 1
127.0.0.1:6379> pfadd a2 3
(integer) 1
127.0.0.1:6379> pfadd a2 3
(integer) 0
127.0.0.1:6379> pfadd a2 4
(integer) 1
127.0.0.1:6379> pfadd a2 4
(integer) 0
127.0.0.1:6379> pfmerge a3 a1 a2
OK
127.0.0.1:6379> pfcount a3
(integer) 5
127.0.0.1:6379>

HyperLogLog总结

应用场景:和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多

HyperLogLog有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么

  • HyperLogLog是一种算法,并非redis独有
  • 目的是做基数统计,不是集合,不会保存原数据,只记录数量而不是数值。耗空间极小,支持海量数据统计。
  • 核心是基数估算算法,主要表现为计算时内存的使用和数据合并的处理。最终数值存在一定误差
  • 误差说明:基数估计的结果是一个带有 0.81% 标准错误(standard error)的近似值。是可接受的范围
  • Redis 对 HyperLogLog 的存储进行了优化,pfadd命令并不是一次性分配12K内存使用,会随着基数的增加内存逐渐增大

GEO

GEO是Redis在3.2版本之后增加的针对于地理位置处理的一种数据类型。主要是用于存储坐标点的经度与维度、通过经度纬度计算两地距离等。

拾取坐标系统

 GEO命令

添加坐标

geoadd key longitude latitude member [longitude latitude member ...]
  • ongitude:经度
  • latitude:纬度
  • member:地点名称

示例:获取"滕王阁"的经度纬度,添加到一个指定集合中。

geoadd nanchang 115.887667 28.687311 twg

获取坐标点

geopos key member [member ...]

示例:查看nanchang地理位置集合中twg的经度纬度

127.0.0.1:6379> geopos nanchang twg
1) 1) "115.88766485452651978"
   2) "28.6873112518150819"
127.0.0.1:6379>

计算两点坐标距离

GEODIST key member1 member2 [unit]
  • unit:单位
    • km:千米
    • m:米(默认)
    • ft:尺
    • ml:英里

示例:添加"八一广场"经度纬度,并计算"滕王阁"与"八一广场"之间的距离

127.0.0.1:6379> geoadd nanchang 115.910937 28.68009 bygc
(integer) 1
127.0.0.1:6379> geopos nanchang twg bygc
1) 1) "115.88766485452651978"
   2) "28.6873112518150819"
2) 1) "115.91093569993972778"
   2) "28.68008983123212374"
127.0.0.1:6379> geodist nanchang twg bygc
"2408.5712"
127.0.0.1:6379>

发现"滕王阁"与"八一广场"之间的距离为2408.5712米

georadius key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]
  • WITHCOORD:返回当前位置的经度纬度
  • WITHDIST:返回当前位置与中心位置之间的距离
  • WITHHASH:返回geohash编码
  • ASC:按离中心距离的位置排序(升序),DESC(降序)
  • COUNT:根据排序结构查询前几位

如图所示,假设我们要以八一馆为中心,计算八一馆附近1000m的地方有那些位置。

1.先将所需要的计算的位置坐标(经度纬度)存储在同一个位置集合中(万寿宫、八一公园)

127.0.0.1:6379> geoadd nanchang 115.892383 28.681013 wsg
(integer) 1
127.0.0.1:6379> geoadd nanchang 115.903594 28.684261 bygy
(integer) 1

2.选择一个坐标点为中心(八一馆),开始计算

127.0.0.1:6379> georadius nanchang 115.898258 28.681615 500 m
(empty list or set)
127.0.0.1:6379> georadius nanchang 115.898258 28.681615 1000 m
1) "wsg"
2) "bygy"
127.0.0.1:6379> georadius nanchang 115.898258 28.681615 2000 m
1) "wsg"
2) "bygy"
3) "twg"
4) "bygc"
127.0.0.1:6379> georadius nanchang 115.898258 28.681615 1500 m
1) "wsg"
2) "bygy"
3) "twg"
4) "bygc"
127.0.0.1:6379> georadius nanchang 115.898258 28.681615 1300 m
1) "wsg"
2) "bygy"
3) "twg"
4) "bygc"
127.0.0.1:6379>

选择额外参数:

127.0.0.1:6379> georadius nanchang 115.898258 28.681615 1000 m withhash
1) 1) "wsg"
   2) (integer) 4051506209236249
2) 1) "bygy"
   2) (integer) 4051506218741151
127.0.0.1:6379> georadius nanchang 115.898258 28.681615 1000 m withcoord
1) 1) "wsg"
   2) 1) "115.89238554239273071"
      2) "28.68101246973412088"
2) 1) "bygy"
   2) 1) "115.9035918116569519"
      2) "28.68426198226040214"
127.0.0.1:6379> georadius nanchang 115.898258 28.681615 1000 m withcoord asc withdist
1) 1) "wsg"
   2) "576.9350"
   3) 1) "115.89238554239273071"
      2) "28.68101246973412088"
2) 1) "bygy"
   2) "597.9623"
   3) 1) "115.9035918116569519"
      2) "28.68426198226040214"
127.0.0.1:6379> georadius nanchang 115.898258 28.681615 1000 m withcoord desc withdist
1) 1) "bygy"
   2) "597.9623"
   3) 1) "115.9035918116569519"
      2) "28.68426198226040214"
2) 1) "wsg"
   2) "576.9350"
   3) 1) "115.89238554239273071"
      2) "28.68101246973412088"
127.0.0.1:6379>
  • 和georadius类似,georadiusbymember命令是以位置集合中某个位置为中心来查询范围内的位置

示例:添加八一馆到nanchang位置集合中,然后以八一馆为中心,查询附近1000m有哪些坐标

127.0.0.1:6379> geoadd nanchang 115.898222 28.681679 byg
(integer) 1
127.0.0.1:6379> georadiusbymember nanchang byg 1000 m
1) "wsg"
2) "byg"
3) "bygy"
127.0.0.1:6379> georadiusbymember nanchang byg 1200 m
1) "wsg"
2) "byg"
3) "bygy"
127.0.0.1:6379> georadiusbymember nanchang byg 1210 m
1) "wsg"
2) "byg"
3) "bygy"
4) "twg"
127.0.0.1:6379>

选择额外参数:

127.0.0.1:6379> georadiusbymember nanchang byg 1000 m
1) "wsg"
2) "byg"
3) "bygy"
127.0.0.1:6379> georadiusbymember nanchang byg 1000 m withcoord withdist
1) 1) "wsg"
   2) "574.3256"
   3) 1) "115.89238554239273071"
      2) "28.68101246973412088"
2) 1) "byg"
   2) "0.0000"
   3) 1) "115.89822202920913696"
      2) "28.68167910139903398"
3) 1) "bygy"
   2) "597.5594"
   3) 1) "115.9035918116569519"
      2) "28.68426198226040214"
127.0.0.1:6379> georadiusbymember nanchang byg 1000 m withcoord withdist desc
1) 1) "bygy"
   2) "597.5594"
   3) 1) "115.9035918116569519"
      2) "28.68426198226040214"
2) 1) "wsg"
   2) "574.3256"
   3) 1) "115.89238554239273071"
      2) "28.68101246973412088"
3) 1) "byg"
   2) "0.0000"
   3) 1) "115.89822202920913696"
      2) "28.68167910139903398"
127.0.0.1:6379>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值