【redis笔记】redis应用

redis应用

redis 发布订阅

redis客户端可以订阅任意数量的频道

订阅方式

subscribe channel1 – 订阅了channel1频道

发布方式

订阅了之后,可以在任意客户端发布消息到指定channel
publish channel1 hello – 往channel发布hello,会返回订阅channel1的数量

redis bitmaps数据类型

redis提供了bitmaps以便对位进行操作,常用于签到、网站用户访问统计(用户id为32或64位,当天访问为1,不访问为0)等场景,命令格式如下:
setbit key offset value 其中,value值为0或1,offset为位的偏移量,从0开始
getbit key offset 获取key的offset位值
bitcount key [start end]获得key中start到end字节中存在bit为1的数量
bitop and/or/not/xor destkey key… 用来做多个bitmaps的复合操作,按位与或非并将结果保存在destkey中

redis hyperLogLog数据类型

常用与实际工作中统计uv,独立ip数,搜索记录数等需要去重和计数的集合中求不重复元素个数的基数问题。
虽然我们像mysql,redis中都有一些方案,像mysql中的distinct count,redis中的hash,set,bitmaps都可以用来处理这类问题,但在数据量很大的时候,存在内存空间问题。HyperLogLog的优势是在数据量非常大时,计算基数所需的空间是很小的,比较固定的。12KB的内存,可以计算接近2^64个元素基数
常用命令有:
pfadd key “xxx” 加入数据xxx,如果已经存在返回0,成功返回1
pfcount key 统计key的数量
pfmerge destkey srckey1 … 将多个key的数据合并到destkey中

geospetial数据类型

redis3.2以上的版本提供了geo的支持,包含了经纬度设置、查询、范围查询、距离查询、经纬度hash等操作。

常用命令

geoadd key latitude longtitude member … 添加一个或多个坐标集合,如geoadd Chinacity 122.34 24.54 xy_1 133.1 56.2 xy_2
有效精度在-180到180之间,有效维度从-85.05112878到85.05112878之间。坐标超出范围返回错误。
geopos key member 获得key集合中member的经纬度
geodist key member1 member [m/km/ft/mi]获得key集合中member1坐标和member2坐标的直线距离,默认距离以m(米为单位)
georadius key latitude longtitude radius [m|km|ft|mi] 以给定坐标为中心,找出某一半径内的元素,半径单位也可以选,默认米

redis事务

redis事务是一个单独的隔离操作,事务中所有命令都会序列化、按顺序地执行,事务在执行过程中,不会被其他客户端发来的命令请求打断,redis事务的作用主要是串联多个命令防止被其他命令插队。

redis事务命令

从输入Multi开始,输入的命令都会依次进入命令队列,但不会被执行,直到输入Exec,redis会将输入的命令依次执行,如果我们在输入命令的过程中,有些命令不想要了,可以用discard命令来丢弃。
如下为示例
在这里插入图片描述

redis事务错误处理

组队的时候如果有命令错误,最终都不会执行。组队命令没问题,执行的过程中有部分命令失败,有错误的命令执行失败,其他命令正常执行。

redis事务冲突与解决机制

为了解决多个请求同时操作同一个值的场景下,我们在编写redis事务操作时,可能认为某个值是A,但实际上在事务入队还没执行之前已经变成了B,如果我们继续按A去操作可能出现问题,从而出现一些非预期的结果(当然也可能没问题,但不可控)。至于像很多地方说的冲突就是10000块的账户减8000,减1000,减5000的问题,如果我就是允许它能为负值,那也没什么问题,我们冲突的关键在与人工判断的部分,我们在执行账户减少的时候我们的当前值是什么,能不能减,而不是只要有同时操作就会冲突。可以通过加锁的方式解决冲突。

悲观锁

每次操作数据都加锁,其他人想访问该数据需要等到锁被释放。传统的关系型数据库大多是这类,如表锁、行锁,都是在操作之前上锁。悲观锁的缺点在于效率比较低。

乐观锁

拿数据的时候不会上锁,在更新的时候判断别人是否有更新,如果有更新,版本不匹配,则不执行更新。判断是否有更新一般使用check-and-set 版本号机制。多用于读数据多的场景。像抢票的时候,我们一般只有一个人成功,其他人都会失败。

案例

在执行multi之前,先使用watch key [keyn…]监视一个或多个需要关注的key,在事务执行前监视的key被改动,事务将被打断。如果不再需要监视了可以在事务中用unwatch取消,如果exec或discard已经执行过了,那就不需要执行unwatch了。
在这里插入图片描述

redis事务的三个特性

  • 单独的隔离操作–事务中所有命令都会序列化、按顺序地执行,不会被其他客户端发来的请求打断。
  • 没有隔离级别–队列中的命令没有提交之前都不会被实际执行
  • 不保证原子性–事务中如果有一条命令失败,其他命令仍然会被执行,没有回滚

多个事务操作同一个变量的解决方案

如果我们在使用事务时,希望能同时对一个变量操作,不要因为一个事务中断另一个事务的操作,比如我们有500张优惠券,希望在还没抢完的情况下,如果有用户同时抢,那么两个都可以抢到,而不是一个的事务影响到另一个,这时可以使用Lua脚本来解决。
一般一些redis客户端会提供lua脚本加载的接口,像jedis,redission中都有。

redis持久化

redis提供了两种持久化方式:RDB(redis database)和AOF(append of file)

RDB

RDB方式是在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的snapshot快照,它恢复时是将快照文件直接读到内存里。比如每过10秒将当前时间点的数据库中的数据写入磁盘。redis在操作的过程中会fork出一个子进程来执行持久化操作,在这个过程中会先写入到一个临时文件,等到持久化过程结束,再将临时文件替换上次保存好的持久化文件。整个过程中主进程是不进行任何IO操作的,因此性能比较高,如果需要大规模的数据恢复,且数据恢复的完整性要求不高,RDB方式要比AOF方式要高效,缺点是可能最后一次持久化的数据会丢失,因为间隔时间可能还没到但服务其挂了。
可以通过修改redis配置来设置RDB的持久化,可以配置成xx时间内有多少个key值变化就执行持久化。
redis启动时会自动加载dump出来的rdb文件
rdb默认开启

AOF

以日志的形式来记录每个写操作,以追加的方式写,redis启动的时候会执行一遍所有的写操作来恢复数据
AOF默认不开启,可以通过修改配置中的appendonly项修改为yes,RDB和AOF同时开启redis优先使用AOF.
redis AOF有异常恢复机制,可以通过/usr/local/bin/redis-check-aof --fix appendonly.aof来恢复
AOF有三种同步方式:
appendfsync always – 总是同步,每次写操作都马上同步到日志,这样保存的日志是最完整的,但同时也会导致性能下降
appendfsync everysec – 每秒同步一次,最多丢失前一秒操作的数据
appendfsync no – 不主动同步,由操作系统来决定什么时候同步

rewrite压缩

为了节省空间,redis有rewrite机制将对同一个元素的多次操作,只记录最终影响的那一次操作,当AOF大小超过阈值后就会启动该机制。也可以使用bgrewriteaof命令重写。当aof文件大于2倍basesize且当前大小大于64MB的情况下,redis会对aof文件重写。重写也是会fork一个子进程,产生一个临时文件,在写完后再替换原aof文件

如何选择持久化方案

如果对数据不敏感,可以用单独用rdb,不建议单独用aof,可能有bug,只做纯缓存用的话可以不用开启

redis应用问题缓存穿透

大量的请求访问redis时,如果较多请求在redis中不存在,频繁地直接查询数据库或访问后端服务,导致数据库或后端服务压力较大而崩溃。
解决方案:

  • 对空值缓存 如果一个查询的返回数据为空,我们仍然对这个空结果做缓存,但需要对这个空值设置过期时间,一般来说过期时间不超过5分钟,但这个方案对攻击的随机性不太适用
  • 设置可访问名单,使用bitmaps定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次均将query和bitmaps里面的id进行对比,效率较低
  • 布隆过滤器,底层是hash加bitmaps,但存在误识别率
  • 实时监控,如果redis的命中率降低,需要排查访问对象

redis缓存击穿

数据库访问压力瞬时增大,但redis中的key并没有出现大量过期,redis也在正常运行,可能原因是:
(1)redis中某个key刚好过期了但大量的访问都涉及到该key(热key)。
(2)在更新redis中数据时,delete老key时请求刚好并发量很大
解决方案:

  • 预先设置热门数据,在高峰访问前,预先存入redis,并加大key的时长或者不设置失效时间
  • 实时监控哪些数据热门,及时调整
  • 互斥更新,双检加锁 在缓存失效时(拿到值为空时),不做任何处理的情况下,我们都会查询数据库来,然后重新设置缓存,这样对数据库的压力就会很大,我们可以先设置一个排他锁,如果排他锁已经存在,说明已经有别的线程在设置数据库更新缓存,如果成功我们再更新缓存,再释放锁。在获取到锁的时候再次查询redis,判断有没有其他用户已经更新过缓存了。

缓存雪崩

在极少时间段内,查询大量key过期的场景,会导致大量的请求直接打到mysql,导致服务器崩溃。
解决方案:

  • 构建多级缓存:nginx缓存+redis缓存+其他缓存
  • 使用锁或队列避免失效时大量并发请求落到底层存储系统上,不适用于高并发
  • 设置过期标志(提前值),过期触发另外的线程去更新该key
  • 分散缓存失效时间,避免key的集体过期

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/255561.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一练2023.12.7—— 情人节【PTA】

题目链接:L1-035 情人节 题目要求: 以上是朋友圈中一奇葩贴:“2月14情人节了,我决定造福大家。第2个赞和第14个赞的,我介绍你俩认识…………咱三吃饭…你俩请…”。现给出此贴下点赞的朋友名单,请你找出…

自定义starter案例——统计独立IP访问次数

自定义starter案例——统计独立IP访问次数 文章目录 自定义starter案例——统计独立IP访问次数ip计数业务功能开发定时任务报表开发使用属性配置功能设置功能参数配置调整 自定义拦截器开启yml提示功能 ip计数业务功能开发 public class IpCountService {private Map<String…

720度vr虚拟家居展厅提升客户的参观兴致

VR虚拟展厅线上3D交互展示的优势有以下几点&#xff1a; 打破了场馆的展示限制&#xff0c;可展示危险性制品、珍贵稀有物品、超大型设备等&#xff0c;同时提供了更大的展示空间和更丰富的展示内容。 可提供企业真实环境的实时VR全景参观&#xff0c;提升潜在客户信任度。 提供…

AMD 发布新芯片MI300,支持训练和运行大型语言模型

AMD 宣布推出 MI300 芯片&#xff0c;其 Ryzen 8040移动处理器将于2024年用于笔记本电脑。 AMD官方网站&#xff1a;AMD ׀ together we advance_AI AMD——美国半导体公司专门为计算机、通信和消费电子行业设计和制造各种创新的微处理器&#xff08;CPU、GPU、主板芯片组、电…

泳道图绘制全攻略,一图胜千言,快速上手

泳道图是一种流程图的形式&#xff0c;通过在不同的泳道中展示不同的参与者&#xff0c;帮助我们更好地理解和分析流程。它是一种非常有用的工具&#xff0c;可以帮助我们在团队协作、流程管理和问题解决等方面取得更好的效果。 1. 泳道图的定义 泳道图是一种以泳道为基础的流程…

刷机操作小记

步骤&#xff1a; 一.刷机 1.先找到刷机包中的刷机命令&#xff0c;然后用sudo的权限对其执行。 2.之后 先短接&#xff0c;再插USB 短接具体图片如下&#xff08;焊口和大板子&#xff09; 此时等待刷机程序执行完毕就可以完成刷机了。 &#xff08;./fh.sh&#xff09; …

指针(四)

因为前期在学驱动&#xff0c;所以花了一天时间借鉴了别的资料&#xff0c;把本科学的C语言捡起来。 指针的基本概念 堆栈有栈顶指针&#xff0c;队列有头指针和尾指针&#xff0c;这些概念中的"指针"本质上是一个整数&#xff0c;是数组的索引&#xff0c;通过指针…

微信小程序收款手续费多少,怎么降低?

在竞争激烈、各行各业都如此内卷的当下&#xff0c;商家需要不断寻求提高利润的方法。所谓开源节流&#xff0c;既要学会提高利润率&#xff0c;也要学会节省成本&#xff0c;毕竟钱是挣出来的&#xff0c;同时也是省出来的。作为一个经常使用收款工具的商家&#xff0c;很多人…

命令查询pg 数据库版本,并且分析结果行各代表什么意思

目录 1 问题2 实现 1 问题 命令查询pg 数据库版本&#xff0c;并且分析结果行各代表什么意思 2 实现 SELECT version(); PostgreSQL 11.7 (Debian 11.7-2.pgdg1001) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit这是一条关于 PostgreSQL 数据库…

Java 线程池到底是如何复用线程的

原理概述 其实 Java 线程池的实现原理很简单&#xff0c;说白了就是一个线程集合 workerSet 和一个阻塞队列 workQueue。 当用户向线程池提交一个任务时&#xff0c;线程池会先将任务放入 workQueue 中。workerSet 中的线程会不断的从 workQueue 中获取线程然后执行。当 work…

软件设计中如何画各类图之六状态图:生动呈现对象生命周期状态转换的重要工具

目录 1 状态图简介2 状态图的符号及说明2.1 状态&#xff08;State&#xff09;2.2 转移&#xff08;Transition&#xff09;2.3 起始状态与终止状态2.4 动作&#xff08;Action&#xff09; 3 画状态图的步骤3.1 确定对象3.2 定义状态3.3 标识转移3.4 标注动作3.5 添加起始和结…

L1-026:I Love GPLT

题目描述 这道超级简单的题目没有任何输入。 你只需要把这句很重要的话 —— “I Love GPLT”——竖着输出就可以了。 所谓“竖着输出”&#xff0c;是指每个字符占一行&#xff08;包括空格&#xff09;&#xff0c;即每行只能有1个字符和回车。 输入样例&#xff1a; 无输出样…