FFmpeg获取视频详情

news/2024/7/26 10:56:29/文章来源:https://blog.csdn.net/myydnz/article/details/137179827

话不多说,直接上代码:

pom依赖:

        <!--视频多媒体工具包 包含 FFmpeg、OpenCV--><dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.3</version></dependency><!-- https://mvnrepository.com/artifact/commons-lang/commons-lang --><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.openjfx</groupId><artifactId>javafx-controls</artifactId><version>16</version></dependency>

工具类:

package com.example.mybatisdemo02.util;import com.example.mybatisdemo02.model.VideoInfoVO;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import org.apache.commons.lang.StringUtils;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import javafx.scene.control.Button;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.util.UUID;public class FFmpegUtil {private static final String IMAGE_SUFFIX = "png";/*** 获取视频时长,单位为秒S* @return*/public static long getVideoTime( String localPath) throws FrameGrabber.Exception {
//        String localPath = "C:/Users/Administrator/Desktop/dab2d14cad0244229e228e7bf297dd9a.flv";FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(localPath);grabber.start();long duration = grabber.getLengthInTime() / (1000 * 1000);grabber.stop();System.out.println("此视频时长(s/秒):"+duration);return duration;}/*** 获取视频帧图片* @param file 视频源* @param number 第几帧* @param dir 文件存放根目录* @param args 文件存放根目录* @return*/@SuppressWarnings("resource")public static String videoImage(File file, Integer number, String dir, String args) {String picPath = StringUtils.EMPTY;FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);try {ff.start();int i = 0;int length = ff.getLengthInFrames();Frame frame = null;while (i < length) {frame = ff.grabFrame();//截取第几帧图片if ((i > number) && (frame.image != null)) {//获取生成图片的路径picPath = getImagePath(args);//执行截图并放入指定位置doExecuteFrame(frame, dir + File.separator + picPath);break;}i++;}ff.stop();} catch (FrameGrabber.Exception e) {e.printStackTrace();}return picPath;}/*** 截取缩略图* @param frame* @param targerFilePath 图片存放路径*/public static void doExecuteFrame(Frame frame, String targerFilePath) {//截取的图片if (null == frame || null == frame.image) {return;}Java2DFrameConverter converter = new Java2DFrameConverter();BufferedImage srcImage = converter.getBufferedImage(frame);int srcImageWidth = srcImage.getWidth();int srcImageHeight = srcImage.getHeight();//对帧图片进行等比例缩放(缩略图)int width = 480;int height = (int) (((double) width / srcImageWidth) * srcImageHeight);BufferedImage thumbnailImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);thumbnailImage.getGraphics().drawImage(srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);File output = new File(targerFilePath);try {ImageIO.write(thumbnailImage, IMAGE_SUFFIX, output);} catch (IOException e) {e.printStackTrace();}}/*** 生成图片的相对路径* @param args 传入生成图片的名称、为空则用UUID命名* @return 例如 upload/images.png*/public static String getImagePath(String args) {if (StringUtils.isNotEmpty(args)) {return args + "." + IMAGE_SUFFIX;}return getUUID() + "." + IMAGE_SUFFIX;}/*** 生成唯一的uuid* @return uuid*/public static String getUUID(){return UUID.randomUUID().toString().replace("-","");}/*** 时长格式换算* @param duration 时长* @return HH:mm:ss*/public static String formatDuration(Long duration) {String formatTime = StringUtils.EMPTY;double time = Double.valueOf(duration);if (time > -1) {int hour = (int) Math.floor(time / 3600);int minute = (int) (Math.floor(time / 60) % 60);int second = (int) (time % 60);if (hour < 10) {formatTime = "0";}formatTime += hour + ":";if (minute < 10) {formatTime += "0";}formatTime += minute + ":";if (second < 10) {formatTime += "0";}formatTime += second;}return formatTime;}/*** 获取图片大小Kb* @param urlPath* @return*/public static String getImageSize(String urlPath){// 得到数据byte[] imageFromURL = getImageFromURL(urlPath);// 转换String byte2kb = bytes2kb(imageFromURL.length);return byte2kb;}/*** 根据图片地址获取图片信息** @param urlPath 网络图片地址* @return*/public static byte[] getImageFromURL(String urlPath) {// 字节数组byte[] data = null;// 输入流InputStream is = null;// Http连接对象HttpURLConnection conn = null;try {// Url对象URL url = new URL(urlPath);// 打开连接conn = (HttpURLConnection) url.openConnection();// 打开读取 写入是setDoOutput
//	        conn.setDoOutput(true);conn.setDoInput(true);// 设置请求方式conn.setRequestMethod("GET");// 设置超时时间conn.setConnectTimeout(6000);// 得到访问的数据流is = conn.getInputStream();// 验证访问状态是否是200 正常if (conn.getResponseCode() == 200) {data = readInputStream(is);} else {data = null;}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if (is != null) {// 关闭流is.close();}} catch (IOException e) {e.printStackTrace();}// 关闭连接conn.disconnect();}return data;}/*** 将流转换为字节** @param is* @return*/public static byte[] readInputStream(InputStream is) {/*** 捕获内存缓冲区的数据,转换成字节数组* ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区,然后利用ByteArrayOutputStream和ByteArrayInputStream的实例向数组中写入或读出byte型数据。* 在网络传输中我们往往要传输很多变量,我们可以利用ByteArrayOutputStream把所有的变量收集到一起,然后一次性把数据发送出去。*/ByteArrayOutputStream baos = new ByteArrayOutputStream();// 创建字节数组 1024 = 1Mbyte[] buffer = new byte[1024];// 防止无限循环int length = -1;try {// 循环写入数据到字节数组while ((length = is.read(buffer)) != -1) {baos.write(buffer, 0, length);}// 强制刷新,扫尾工作,主要是为了,让数据流在管道的传输工程中全部传输过去,防止丢失数据baos.flush();} catch (IOException e) {e.printStackTrace();}// 字节流转换字节数组byte[] data = baos.toByteArray();try {// 关闭读取流is.close();// 关闭写入流baos.close();} catch (IOException e) {e.printStackTrace();}return data;}/*** 获取本地图片的字节数** @param imgPath* @return*/public static String pathSize(String imgPath) {File file = new File(imgPath);FileInputStream fis;int fileLen = 0;try {fis = new FileInputStream(file);fileLen = fis.available();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return bytes2kb(fileLen);}/*** 将获取到的字节数转换为KB,MB模式** @param bytes* @return*/public static String bytes2kb(long bytes) {BigDecimal filesize = new BigDecimal(bytes);
//        BigDecimal megabyte = new BigDecimal(1024 * 1024);
//        float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP).floatValue();
//        if (returnValue > 1)
//            return (returnValue + "MB");
//        BigDecimal kilobyte = new BigDecimal(1024);
//        returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
//        return (returnValue + "KB");return filesize.toString();}public static String getImageFormat(String imagePath) throws IOException {// 字节数组byte[] data = null;String format = null;// 输入流InputStream is = null;// Http连接对象HttpURLConnection conn = null;ImageInputStream imageInputStream = null;try {// Url对象URL url = new URL(imagePath);// 打开连接conn = (HttpURLConnection) url.openConnection();// 打开读取 写入是setDoOutput
//	        conn.setDoOutput(true);conn.setDoInput(true);// 设置请求方式conn.setRequestMethod("GET");// 设置超时时间conn.setConnectTimeout(6000);// 得到访问的数据流is = conn.getInputStream();// 验证访问状态是否是200 正常if (conn.getResponseCode() == 200) {imageInputStream = ImageIO.createImageInputStream(is);ImageReader imageReader = ImageIO.getImageReaders(imageInputStream).next();format = imageReader.getFormatName();} else {format = null;}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {if (is != null) {// 关闭流is.close();}if(imageInputStream != null){imageInputStream.close();}} catch (IOException e) {e.printStackTrace();}// 关闭连接conn.disconnect();}return format;}/*** 将inputStream转化为file* @param is* @param file 要输出的文件目录*/public static void inputStream2File(InputStream is, File file) throws IOException {OutputStream os = null;try {os = new FileOutputStream(file);int len = 0;byte[] buffer = new byte[8192];while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}} finally {os.close();is.close();}}/*** 获取视频详情* @param file* @return*/public static VideoInfoVO getVideoInfo(String file) {VideoInfoVO videoInfoVO = new VideoInfoVO();FFmpegFrameGrabber grabber = null;try {grabber = FFmpegFrameGrabber.createDefault(file);// 启动 FFmpeggrabber.start();// 读取视频帧数videoInfoVO.setLengthInFrames(grabber.getLengthInVideoFrames());// 读取视频帧率videoInfoVO.setFrameRate(grabber.getVideoFrameRate());// 读取视频秒数videoInfoVO.setDuration(grabber.getLengthInTime() / 1000000.00);// 读取视频宽度videoInfoVO.setWidth(grabber.getImageWidth());// 读取视频高度videoInfoVO.setHeight(grabber.getImageHeight());videoInfoVO.setAudioChannel(grabber.getAudioChannels());videoInfoVO.setVideoCode(grabber.getVideoCodecName());videoInfoVO.setAudioCode(grabber.getAudioCodecName());// String md5 = MD5Util.getMD5ByInputStream(new FileInputStream(file));videoInfoVO.setSampleRate(grabber.getSampleRate());return videoInfoVO;} catch (Exception e) {e.printStackTrace();return null;} finally {try {if (grabber != null) {// 此处代码非常重要,如果没有,可能造成 FFmpeg 无法关闭grabber.stop();grabber.release();}} catch (FFmpegFrameGrabber.Exception e) {e.printStackTrace();}}}/*** 截取视频获得指定帧的图片(截取视频帧封面)** @param video   源视频文件*/public void getVideoPic(InputStream video) {FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);try {ff.start();// 截取中间帧图片(具体依实际情况而定)int i = 0;int length = ff.getLengthInFrames();
//            int middleFrame = length / 2;int middleFrame = 5;Frame frame = null;while (i < length) {frame = ff.grabFrame();if ((i > middleFrame) && (frame.image != null)) {break;}i++;}// 截取的帧图片Java2DFrameConverter converter = new Java2DFrameConverter();BufferedImage srcImage = converter.getBufferedImage(frame);int srcImageWidth = srcImage.getWidth();int srcImageHeight = srcImage.getHeight();BufferedImage image = new BufferedImage(srcImageWidth, srcImageHeight, BufferedImage.TYPE_INT_ARGB);Graphics2D g2d = image.createGraphics();g2d.setColor(Color.RED);g2d.fillRect(0, 0, srcImageWidth, srcImageHeight);g2d.setColor(Color.WHITE);g2d.drawString("Hello, World!", 50, 100);g2d.dispose();File file = new File("image.png");try {ImageIO.write(image, "png", file);} catch (IOException e) {e.printStackTrace();}ff.stop();} catch (java.lang.Exception e) {e.printStackTrace();System.out.println(e);}}/*** 获取文件大小* @param inputStream* @return*/public String getFileSize(InputStream inputStream){FileChannel fc = null;String size = "0";try {FileInputStream fis = convertToFileInputStream(inputStream);fc = fis.getChannel();BigDecimal fileSize = new BigDecimal(fc.size());size = String.valueOf(fileSize);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (null != fc) {try {fc.close();} catch (IOException e) {e.printStackTrace();}}}return size;}/*** inputStream转FileInputStream* @param inputStream* @return* @throws IOException*/public static FileInputStream convertToFileInputStream(InputStream inputStream) throws IOException {File tempFile = File.createTempFile("temp", ".tmp");tempFile.deleteOnExit();try (FileOutputStream outputStream = new FileOutputStream(tempFile)) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}return new FileInputStream(tempFile);}public void start(Stage primaryStage) {String videoPath = "C:\\Users\\DELL\\Desktop\\test.mp4";double position = 1200.0; // 播放位置(以秒为单位)// 创建媒体播放器Media media = new Media(new File(videoPath).toURI().toString());MediaPlayer mediaPlayer = new MediaPlayer(media);mediaPlayer.setOnReady(() -> {mediaPlayer.seek(mediaPlayer.getTotalDuration().multiply(position / mediaPlayer.getTotalDuration().toSeconds()));mediaPlayer.play();});mediaPlayer.setAutoPlay(true);// 创建媒体视图MediaView mediaView = new MediaView(mediaPlayer);// 创建控制按钮Button playButton = new Button("播放");Button pauseButton = new Button("暂停");Button stopButton = new Button("停止");// 播放按钮点击事件playButton.setOnAction(event -> mediaPlayer.play());// 暂停按钮点击事件pauseButton.setOnAction(event -> mediaPlayer.pause());// 停止按钮点击事件stopButton.setOnAction(event -> mediaPlayer.stop());// 创建音量调节滑块Slider volumeSlider = new Slider(0, 1, 0.5);volumeSlider.setPrefWidth(100);mediaPlayer.volumeProperty().bind(volumeSlider.valueProperty());// 创建按钮布局HBox buttonBox = new HBox(10);buttonBox.setAlignment(Pos.CENTER);buttonBox.getChildren().addAll(playButton, pauseButton, stopButton);// 创建根布局BorderPane root = new BorderPane();root.setCenter(mediaView);root.setBottom(volumeSlider);root.setTop(buttonBox);// 创建场景Scene scene = new Scene(root, 800, 600);// 设置舞台primaryStage.setScene(scene);primaryStage.setTitle("Video Player");primaryStage.show();}
}
实体VideoInfoVO类:
package com.example.mybatisdemo02.model;import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;@Getter
@Setter
public class VideoInfoVO {/*** 总帧数**/private int lengthInFrames;/*** 帧率**/private double frameRate;/*** 时长**/private double duration;/*** 视频编码*/private String videoCode;/*** 音频编码*/private String audioCode;private int width;private int height;private int audioChannel;private String md5;/*** 音频采样率*/private Integer sampleRate;private Double fileSize;public String toJson() {try {ObjectMapper objectMapper = new ObjectMapper();return objectMapper.writeValueAsString(this);} catch (Exception e) {return "";}}
}

调用:

public class Main {public static void main(String[] args) {VideoInfoVO videoInfoVO = FFmpegUtil.getVideoInfo("C:\\Users\\DELL\\Desktop\\test.mp4");int date = videoInfoVO.getLengthInFrames();double shichang = videoInfoVO.getDuration();System.out.println("帧数:"+date+"时长:"+shichang);}
}

结果如下图:

欢迎给个关注:

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

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

相关文章

使用ffmpeg将视频解码为帧时,图像质量很差

当使用ffmpeg库自带的ffmpeg.exe对对视频进行解帧或合并时&#xff0c;结果质量很差。导致这种原因的是在使用ffmpeg.exe指令进行解帧或合并时使用的是默认的视频码率&#xff1a;200kb/s。 如解帧指令&#xff1a; ffmpeg.exe -i 600600pixels.avi -r 2 -f image2 img/%03d.…

Java项目:86 springboot电影评论网站系统设计与实现

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本电影评论网站管理员和用户。 管理员功能有个人中心&#xff0c;用户管理&#xff0c;电影类别管理&#xff0c;电影信息管理&#xff0c;留言板管理…

自贡市第一人民医院:超融合与 SKS 承载 HIS 等核心业务应用,加速国产化与云原生转型

自贡市第一人民医院始建于 1908 年&#xff0c;现已发展成为集医疗、科研、教学、预防、公共卫生应急处置为一体的三级甲等综合公立医院。医院建有“全国综合医院中医药工作示范单位”等 8 个国家级基地&#xff0c;建成高级卒中中心、胸痛中心等 6 个国家级中心。医院日门诊量…

wife_wife【web 攻防世界】

大佬的wp:WEB&#xff1a;Wife_wife-CSDN博客 知识点&#xff1a; prototype是new class 的一个属性&#xff0c;即__proto__指向new class 的prototype属性__proto__如果作为json代码解析的话会被当成键名处理&#xff0c;但是如果是在类中的话则会被当成子类的原型 如let o…

Catcatcat【杂项 攻防世界】

知识点&#xff1a; strings 命令 打印文件中可以打印的字符&#xff0c;可以是任意文件grep flag 过滤出文件中的flag关键字rabbit加密 深入了解Rabbit加密技术&#xff1a;原理、实现与应用-CSDN博客对称加密算法需要密钥&#xff0c;也可不设置数据开头固定&#xff1a;U2F…

二百二十九、离线数仓——离线数仓Hive从Kafka、MySQL到ClickHouse的完整开发流程

一、目的 为了整理离线数仓开发的全流程&#xff0c;算是温故知新吧 离线数仓的数据源是Kafka和MySQL数据库&#xff0c;Kafka存业务数据&#xff0c;MySQL存维度数据 采集工具是Kettle和Flume&#xff0c;Flume采集Kafka数据&#xff0c;Kettle采集MySQL数据 离线数仓是Hi…

C++ 2024-4-1 作业

#include <iostream> using namespace std;class A { public:int a;A(int a):a(a){cout<<"A的有参构造"<<endl;} }; class B:virtual public A { public:int b;B(int a,int b):A(a),b(b){cout<<"B的有参构造"<<endl;} }; cl…

论文笔记 - :DIGGING INTO OUTPUT REPRESENTATION FOR MONOCULAR 3D OBJECT DETECTION

Title: 深入研究单目 3D 物体检测的输出表示 Abstract 单目 3D 对象检测旨在从单个图像中识别和定位 3D 空间中的对象。最近的研究取得了显着的进展&#xff0c;而所有这些研究都遵循基于 LiDAR 的 3D 检测中的典型输出表示。 然而&#xff0c;在本文中&#xff0c;我们认为…

VScode debug python(服务器)

方法一&#xff1a; 创建launch.json文件&#xff1a; launch.json文件地址&#xff1a; launch.json文件内容&#xff1a; {"version": "0.2.0", //指定了配置文件的版本"configurations": [{"name": "Python: Current File&…

Java设计之道:色即是空,空即是色

0.引子 我们的这个世界上&#xff0c;存在这么一种东西&#xff1a; 第一&#xff1a;它不占据任何3D之体积&#xff0c;即它没有Volume第二&#xff1a;它也不占据任何2D之面积&#xff0c;即它没有Area第三&#xff1a;它也不占据任何1D之长度&#xff0c;即它没有Length 总…

合并两个单链表

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 但行前路&#xff0c;不负韶华&#…

微信小程序自定义弹窗组件

业务背景&#xff1a;弹窗有时字体较多&#xff0c;超过7个字&#xff0c;不适用wx.showToast. 组件代码 <view class"toast-box {{isShow? show:}}" animation"{{animationData}}"><view class"toast-content" ><view class&q…

Go-Gin中优雅的实现参数校验,自定义错误消息提示

问题描述 在参数校验的时候我们一般会基于"github.com/go-playground/validator/v10"这个库给结构体加标签实现校验参数&#xff0c;当参数校验错误的时候&#xff0c;他的提示一般是英文的&#xff0c;怎么自定义参数错误提示呢&#xff1f;跟着我一步步来 注册校…

抖音无水印视频采集软件|视频批量提取工具

轻松获取抖音无水印视频&#xff0c;一键提取&#xff0c;快速下载&#xff01; 正文&#xff1a; 想要获取抖音上的精彩视频&#xff0c;但又苦于找不到无水印的版本&#xff1f;现在&#xff0c;有了我们的抖音无水印视频采集软件&#xff0c;Q:290615413您可以轻松实现关键…

vue结合Elempent-Plus/UI穿梭框更改宽度以及悬浮文本显示

由于分辨率不同会导致文本内容显示不全&#xff0c;如下所示&#xff1a; 因此需要 1、悬浮到对应行上出现悬浮信息 实现代码如下所示&#xff1a; 这里只演示Vue3版本代码&#xff0c;Vue2版本不再演示 区别就在插槽使用上Vue3使用&#xff1a;#default“”&#xff1b;Vu…

Discuz! X3.5苗木_苗木网_苗木价格_苗木求购信息_苗木批发网模板utf-8

适合做苗木行业平台苗木网站、苗木信息网,提供苗木报价、各地苗木求购信息、绿化苗木采购招标、苗木基地展示、苗木百科知识、花木交易及苗木资讯、各地苗木信息网络行情。解压上传到template目录下&#xff0c;后台安装即可&#xff0c;包含PC手机端模板 下载地址&#xff1a;…

1.Git是用来干嘛的

Git就是一个文件管理系统&#xff0c;这样说吧&#xff0c;当多个人同时在操作一个文件的同时&#xff0c;很容易造成紊乱&#xff0c;git就是保证文件不紊乱产生的 包括集中式管理系统和分布式管理系统 听懂了&#xff0c;集中式管理系统就是从中央服务器上下载最新的版本文件…

OSError: Can‘t load tokenizer for ‘bert-base-chinese‘

文章目录 OSError: Cant load tokenizer for bert-base-chinese1.问题描述2.解决办法 OSError: Can’t load tokenizer for ‘bert-base-chinese’ 1.问题描述 使用from_pretrained()函数从预训练的权重中加载模型时报错&#xff1a; OSError: Can’t load tokenizer for ‘…

CentOS 7 下离线安装RabbitMQ教程

CentOS 7 下安装RabbitMQ教程一、做准备&#xff08;VMWare 虚拟机上的 CentOS 7 镜像 上安装的&#xff09; &#xff08;1&#xff09;准备RabbitMQ的安装包&#xff08;rabbitmq-server-3.8.5-1.el7.noarch&#xff09;下载地址mq https://github.com/rabbitmq/rabbitmq-se…

Redis缓存设计与性能优化【缓存和数据库不一致问题,解决方案:1.加过期时间这样可以一段时间后自动刷新 2.分布式的读写锁】

Redis缓存设计与性能优化 缓存与数据库双写不一致 缓存与数据库双写不一致 在大并发下&#xff0c;同时操作数据库与缓存会存在数据不一致性问题 1、双写不一致情况 2、读写并发不一致 解决方案&#xff1a; 1、对于并发几率很小的数据(如个人维度的订单数据、用户数据等)&a…