redis中的事务,键的过期时间以及排序

事务(MULTI)

Redis中的事务是一组命令的集合,事务同命令一样都是Redis的最小执行单位,一个事务中的命令要么都执行,要么都不执行

原理:

  • 先将MULTI命令发送给Redis,告诉Redis我要开启一个事务
  • 之后Redis将收到的命令全部放到一个事务队列中,暂不执行
  • 直到收到EXEC命令,Redis会将等待执行的事务队列中的命令按照发送顺序依次执行,返回值顺序和命令的顺序相同
  • Redis还能保证一个事务内的命令依次执行而不被其他命令插入
  • Redis不支持回滚操作,语法错误其余命令都不会执行,命令与数据类型不匹配等运行错误就算出现,其余命令还是会执行,如果出现错误就只能自己去解决这个问题了

WATCH

  • WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会被执行,监控一直持续到EXEC命令
  • 由于WATCH命令的作用只是当被监控的键值被修改后阻止之后一个事务的执行,而不能保证其他客户端不修改这一键值,所以我们需要在EXEC执行失败后重新执行整个函数
  • 执行EXEC命令后会取消对所有键的监控,如果不想执行事务中的命令也可以使用UNWATCH命令来取消监控

过期时间

设置过期时间(EXPIRE)

SET name xiaoming
EXPIRE name 20

查询过期时间(TTL)

TTL name
  • EXPIRE命令使用方法为EXPIRE key seconds,seconds表示键的过期时间,单位是秒
  • PEXPIRE命令更精确的控制过期时间,单位为毫秒,PTTL key 查看以毫秒为单位的过期时间
  • EXPIREAT命令是使用Unix时间作为第二个参数表示键的过期时刻

设置缓存淘汰键的规则

当服务器内存有限时,如果大量的使用缓存键且过期时间设置的很长就会导致redis占满内存
另一方面如果为了防止redis占用内存过大而将缓存键的过期时间设置的太短,就可能导致缓存命中率过低并且大量的内存白白的闲置.
实际开发中会发现很难为缓存键设置合理的过期时间,为此可以限制redis能够使用的最大内存,并让redis按照一定的规则淘汰不需要的缓存键,
这种方式在只将redis用作缓存系统时非常实用

具体设置方法: 修改配置文件中的maxmemory参数,限制redis最大可用内存大小(单位是字节),
当超出这个限制时会一句maxmemory-policy参数指定的策略来删除不需要的键,直到redis占用的内存小于指定内存

规则 说明
volatile-lru 使用LRU算法删除一个键(只对设置了过期时间的键)
allkeys-lru 使用LRU算法删除一个键
volatile-random 随机删除一个键(只对设置了过期时间的键)
allkeys-random 随机删除一个键
volatile-ttl 删除过期时间最近的一个键
noeviction 不删除键,只返回错误

LRU算法:最近最少使用,其认为最近最少使用的键在未来一段时间内也不会被用到,即当需要空间时这些键是可以被删除的

提示:使用allkeys-lru规则时,事实上redis并不会准确的将整个数据库中最久未被使用的键删除,而是每次从数据库中随机取3个键并删除这三个键中最久未被使用的键,
删除过期时间最接近的键的实现方也是这样,"3"这个数字可以通过redis的配置文件中的maxmemory-samples参数设置

排序

sort命令排序

功能:sort可以对列表类型,集合类型和有序集合类型进行排序,并且可以完成与关系数据库中的连接查询相类似的任务

SORT key
  • 在对有序集合类型排序时会忽略元素的分数,只针对元素自身的值进行排序
  • 除了可以排列数字外,sort命令还可以通过ALPHA参数实现按照字典顺序排列非数字元素
LPUSH mylistalpha a c e d B C A
SORT mylistalpha ALPHA --> A B C a c d e
  • SORT命令默认是按照从小到大的顺序排列的,DESC参数可以将元素按照从大到小排列
SORT numbers DESC
  • SORT命令还支持LIMIT参数来返回指定范围的结果LIMIT offset count,表示跳过前offset个元素并获取之后的count个元素
SORT numbers DESC LIMIT 1 2

SORT中的BY参数

  • BY参数的语法为BY 参考键,其中参考键可以是字符串类型或者是散列类型键的某个字段(表示为键名->字段名),如果提供了BY参数,SORT命令将不再依据元素
    自身的值进行排序,而是对每个元素使用元素的值替换参考键中的第一个"*"并获取其值,然后一句该值对元素排序
SORT tag:name BY post:*->time DESC
参考键还可以是字符串类型
LPUSH sortbylist 1 2 3
SET itemscore:1 50
SET itemscore:2 100
SET itemscore:3 -10
SORT sortbylist BY itemscore:* DESC
  • 当参考键名不包含"*"时(即常量键名,与元素值无关),SORT命令将不会执行排序操作,常用于不需要排序但需要借助SORT命令获得与元素相关联的数据时
  • 如果几个元素的参考键值相同,则SORT命令会再比较元素本身的值来决定元素的顺序
  • 参考键虽然支持散列类型,但是"*“只能在”->“符号前面(即键名部分才有用),在”->"后(即字段名部分)会被当成字段名本身而不会作为占位符被元素的值替换,
    即常量键名,这时由于每个元素的参考键值都是相同的,所以redis会按照元素本身的大小排列

SORT中的GET参数

  • GET参数不影响排序,它的作用是使SORT命令的返回结果不再是元素自身的值,而是GET参数中指定的键值,
  • GET参数也支持字符串类型和散列类型的键,并使用"*"作为占位符.
  • 在一个SORT命令中可以有多个GET参数(而BY参数只能有一个)
  • GET # 会返回元素本身的值
SORT tag:ports BY post:*->time DESC GET post:*->title GET post:*->time

SORT中的STORE参数

  • 默认情况下SORT会返回排序结果,使用STORE参数保留排序结果,如果要把结果保存到sort.result键中,
SORT tag:posts BY post:*->time DESC GET post:*->title GET post:*->time GET # STORE sort.result
  • 加上STORE参数后SORT命令的返回值为结果的个数,保存的sort.result键的类型为列表类型
  • STORE参数通常用来结合EXPIRE命令缓存排序结果

SORT性能优化

  • SORT命令的时间复杂度为O(n+mlog(m)),其中n表示要排序的列表(集合或有序集合)中的元素个数,m表示要返回的元素个数
  • 当n较大的时候SORT命令的性能会相对较低,并且redis在排序前会建立一个长度为n的容器来存储待排序的元素,如果同时进行较大的大数据量排序操作会严重影响性能

注意:

  • 尽可能减少待排序键中元素的数量(使n尽可能小)
  • 使用LIMIT参数只获取需要的数据(使m尽可能小)
  • 如果要排序的数据量较大,尽可能使用STORE参数将结果缓存
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章