Redis基础知识概述

Redis基础知识概述


文章目录

一、Redis简介

1、Redis(Remote Dictionary Server 远程字段服务)是一个开源的使用ANSI C语言编写、支持网络、科技与内存亦可持久化的日志型、key-value数据库,并提供多种语言的API。

2、Redis是一个key-value存储系统,它支持存储的value类型相对更多,包括string、list、set、zset(sorted set --有序集合)和hash。这些数据结构都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中,Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

3、Redis提供了java、C/C++、PHP、JavaScript、Perl、Object-C、Python、Ruby、Erlang等客户端,使用很方便。

4、Reids支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他服务器的主服务器。这使得Redis可执行单层数复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

5、 在我们日常的Java Web开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tLb9zQWV-1682565151611)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20230421095843441.png)]

二、NoSQL技术

为了克服上述问题,java web项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。

Redis和MongoDB是当前使用最广泛的NoSQL, 而就Redis技术而言,它的性能十分优越,可以支持每秒十几万的读写操作,其性能远超数据库,并且还支持集群、。分布式、主从同步等配置,原则上可以无限扩展,让更多的数据存储在内存中,更让人欣慰的是它还支持一定的事务能力,这保证了高并发的场景下数据的安全和一致性。

三、Redis的高并发和快速原因

1.Redis是基于内存的,内存的读写速度非常快;
2.Redis是单线程的,省去了很多上下文切换线程的时间;
3.Redis使用多路复用技术,可以处理并发的连接。非IO内部实现采用epoll,采用了epoll自己实现的简单的事件框架。epoll的读写、关闭、连接都转化为事件,然后利用epoll的多路复用特性,绝不在IO上浪费一点时间。

四、Redis为什么是单线程的

1、官方解释

Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络宽带。既然单线程容易实现,而且CPU不会成为瓶颈,那么顺理成章的采用单线程的方案。

2、详细原因
(1)不需要各种锁的性能消耗

Redis的数据结构并不全是key-value形式的,还有list,hash等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在hash中添加或删除一个对象,这些操作可能就需要加非常多的锁,导致的结果是同步开销大大增加。

总之,在单线程的情况下,就不用去考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现的死锁而导致的性能消耗。

(2)单线程多进程集群方案

单线程的威力实际上非常强大,每核心效率也非常高,多线程自然是可以比单线程有更高的性能上限,但是在今天的计算环境中,即使是单机多线程的上限也往往不能满足需要了,需要进一步摸索的是多服务器集群化的方案,这些方案中多线程的技术照样是用不上的。

所以单线程、多进程的集群不失为一个时髦的解决方案。

(3)CPU消耗

采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU。

但是如果CPU称为Redis的瓶颈,或者不想让服务器其它CPU核闲置,那怎么办?

可以考虑多起几个Redis进程,Redis是key-value数据库,不是关系型数据库,数据之间没有约束。只要客户端分清哪些key放在哪个Redis进程中就可以了。

五、单线程的优劣势

1、优势

  1. 代码更清晰,处理逻辑更简单
  2. 不用考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现死锁而导致的性能消耗
  3. 不存在多线程切换而消耗CPU

2、劣势

无法发挥多核CPU性能优势,不过可以通过单击开多个Redis实例来完善。

六、Redis高并发总结

1、Redis是纯内存数据库,一般都是简单存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快;

2、Redis使用的是非阻塞IO,IO多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成事件,减少了线程切换时上下文切换和竞争。

3、Redis采用了单线程的模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。

4、Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如跳表,使用有序的数据结构加快读写的速度。

5、Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。

七、在java中使用Redis

1、添加Jedis依赖

想要在 Java 中使用 Redis 缓存,需要添加相关的Jar包依赖,打开Maven仓库的网站:https://mvnrepository.com/ ,搜索Jedis:

img

把它导入工程中去就可以啦,下面我们来对Redis的写入性能做一下测试:

@Test
public void redisTester() {
    Jedis jedis = new Jedis("localhost", 6379, 100000);
    int i = 0;
    try {
        long start = System.currentTimeMillis();// 开始毫秒数
        while (true) {
            long end = System.currentTimeMillis();
            if (end - start >= 1000) {// 当大于等于1000毫秒(相当于1秒)时,结束操作
                break;
            }
            i++;
            jedis.set("test" + i, i + "");
        }
    } finally {// 关闭连接
        jedis.close();
    }
    // 打印1秒内对Redis的操作次数
    System.out.println("redis每秒操作:" + i + "次");
}
-----------测试结果-----------
redis每秒操作:10734

2、使用Redis连接池

跟数据库连接池相同,Java Redis也同样提供了类 redis.clients.jedis.JedisPool来管理我们的Reids连接池对象,并且我们可以使用 redis.clients.jedis.JedisPoolConfig来对连接池进行配置,代码如下:

JedisPoolConfig poolConfig = new JedisPoolConfig();
// 最大空闲数
poolConfig.setMaxIdle(50);

// 最大连接数
poolConfig.setMaxTotal(100);

// 最大等待毫秒数
poolConfig.setMaxWaitMillis(20000);

// 使用配置创建连接池
JedisPool pool = new JedisPool(poolConfig, "localhost");

// 从连接池中获取单个连接
Jedis jedis = pool.getResource();

// 如果需要密码
//jedis.auth("password");

Redis只能支持六种数据结构 (string/hash/list/set/zset/hyperloglog)的操作 ,但在Java中我们通常以类对象为主,所以在Redis存储的数据结构月java对象之间进行转换,如自己编写一些工具类 比如一个角色对象的转换,还是比较容易的,但是涉及到许多对象的时候,这其中无论工作量还是工作难度都是很大的,所以总体来说, 就操作对象而言,使用Redis还是挺难的,好在spring对这些进行了封装和支持。

八、Redis在Java Web中的应用

Redis 在 Java Web 主要有两个应用场景:

  • 存储缓存用的数据
  • 需要高速读写的场合

1、存储缓存用的数据

在日常对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用SQL语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。

如果放在Redis中,也就是放在内存中,让服务器直接读取内存中的数据,那么速度就会快很多,并且会极大减少数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用Redis存储一些常用的和主要的数据,比如用户登录信息等。

一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:

(1)业务数据常用吗?使用率如何?

如果使用率较低,就没必要写入缓存。

(2)该业务是读操作多,还是写操作多?

如果写操作多,频繁需要写入数据库,也没必要使用缓存。

(3)业务数据大小如何?

如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没必要。

在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它!使用 Redis 作为缓存的读取逻辑如下图所示:

img

从上图我们可以知道以下两点:

(1)当第一次读取数据的时候,读取Redis的数据就会失败,此时就会触发程序读取数据库,把数据读取出来,并且写入Redis中

(2)当第二次以及以后需要读取数据时,就会直接读取Redis,读取数据后就结束了流程,这样速度大大提高了。

从上面的分析可以知道,读操作的可能性是远大于写操作的,所以使用 Redis 来处理日常中需要经常读取的数据,速度提升是显而易见的,同时也降低了对数据库的依赖,使得数据库的压力大大减少。

分析了读操作的逻辑,下面我们来看看写操作流程:

img

从流程可以看出,更新或者写入的操作,需要多个 Redis 的操作,如果业务数据写次数远大于读次数那么就没有必要使用 Redis。

2、高速读写场合

在如今的互联网中,越来越多的存在高并发的情况,比如天猫双11、抢红包、抢演唱会门票等,这些场合都是在某一个瞬间或者是某一个短暂的时刻有成千上万的请求到达服务器,如果单纯的使用数据库来进行处理,就算不崩,也会很慢的,轻则造成用户体验极差用户量流水,重则数据库瘫痪,服务宕机,而这样的场合都是不允许的!

所以我们需要使用 Redis 来应对这样的高并发需求的场合,我们先来看看一次请求操作的流程:

img

我们来进一步阐述这个过程:

(1)当一个请求到达服务器时,只是把业务数据在Redis上进行读写,而没有对数据库进行任何的操作,这样就能大大提高读写的速度,从而满足高速相应的需求。

(2)但是这些缓存的数据仍然需要持久化,也就是存入数据库之中,所以在一个请求操作完Redis的读写之后,会去判断该高速读写的业务是否结束,这个判断通常会在秒杀商品为0,红包金额为0时成立,如果不成立,则不会操作数据库;如果成立,则触发事件将Redis的缓存的数据以批量的形式一次性写入数据库,从而完成持久化的工作。

九、在spring中使用Redis

上面说到了 Redis 无法操作对象的问题,无法在那些基础类型和 Java 对象之间方便的转换,但是在 Spring 中,这些问题都可以通过使用RedisTemplate得到解决!

想要达到这样的效果,除了 Jedis 包以外还需要在 Spring 引入 spring-data-redis 包。

1、使用spring配置JedisPoolConfig对象

大部分的情况下,我们还是会用到连接池的,于是先用 Spring 配置一个 JedisPoolConfig 对象:

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    
    <!--最大空闲数-->
    <property name="maxIdle" value="50"/>

    <!--最大连接数-->
    <property name="maxTotal" value="100"/>

    <!--最大等待时间-->
    <property name="maxWaitMillis" value="20000"/>

</bean>

2、为连接池配置工厂模型

好了,我们现在配置好了连接池的相关属性,那么具体使用哪种工厂实现呢?在Spring Data Redis中有四种可供我们选择的工厂模型,它们分别是:

  • JredisConnectionFactory
  • JedisConnectionFactory
  • LettuceConnectionFactory
  • SrpConnectionFactory

我们这里就简单配置成JedisConnectionFactory:

<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">

    <!--Redis服务地址-->
    <property name="hostName" value="localhost"/>

    <!--端口号-->
    <property name="port" value="6379"/>

    <!--如果有密码则需要配置密码-->
    <!--<property name="password" value="password"/>-->

    <!--连接池配置-->
    <property name="poolConfig" ref="poolConfig"/>

</bean>

3、配置RedisTemplate

普通的连接根本没有办法直接将对象直接存入 Redis 内存中,我们需要替代的方案:将对象序列化(可以简单的理解为继承Serializable接口)。我们可以把对象序列化之后存入Redis缓存中,然后在取出的时候又通过转换器,将序列化之后的对象反序列化回对象,这样就完成了我们的要求:

img

RedisTemplate可以帮助我们完成这份工作,它会找到对应的序列化器去转换Redis的键值:

<bean id="redisTemplate"
      class="org.springframework.data.redis.core.RedisTemplate"
      p:connection-factory-ref="connectionFactory"/>

4、测试

首先编写好支持我们测试的POJO类:

/**
 * @author: 素小暖
 * @create: 2020-2-12
 */

public class Student implements Serializable{
    private String name;
    private int age;

    /**    
     * 给该类一个服务类用于测试
     */
    
    public void service() {
        System.out.println("学生名字为:" + name);
        System.out.println("学生年龄为:" + age);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

然后编写测试类:

@Test
public void test() {
    ApplicationContext context =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    RedisTemplate redisTemplate = context.getBean(RedisTemplate.class);
    Student student = new Student();
    student.setName("我没有三颗心脏");
    student.setAge(21);
    redisTemplate.opsForValue().set("student_1", student);
    Student student1 = (Student) redisTemplate.opsForValue().get("student_1");
    student1.service();
}

十、springboot中使用Redis

1、在springboot中添加Redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、添加配置文件application.peoperties

# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0

# Redis服务器地址
spring.redis.host=localhost

# Redis服务器连接端口
spring.redis.port=6379

# Redis服务器连接密码(默认为空)
spring.redis.password=

# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8

# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1

# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8

# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0

# 连接超时时间(毫秒)
spring.redis.timeout=0

3、测试访问

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest()
public class ApplicationTests {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    public void test() throws Exception {
        // 保存字符串
        stringRedisTemplate.opsForValue().set("aaa", "111");
        Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa"));
    }
}

通过上面这段极为简单的测试案例演示了如何通过自动配置的StringRedisTemplate对象进行Redis的读写操作,该对象从命名中就可注意到支持的是String类型。原本是RedisTemplate<K, V>接口,StringRedisTemplate就相当于RedisTemplate<String, String>的实现。

4、存储对象

这一步跟上面使用Spring一样,只需要将POJO类实现Serializable接口就可以了,我这里就贴一下测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest()
public class ApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void test() throws Exception {
        User user = new User();
        user.setName("我没有三颗心脏");
        user.setAge(21);
        redisTemplate.opsForValue().set("user_1", user);
        User user1 = (User) redisTemplate.opsForValue().get("user_1");
        System.out.println(user1.getName());
    }
}
icationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void test() throws Exception {
        User user = new User();
        user.setName("我没有三颗心脏");
        user.setAge(21);
        redisTemplate.opsForValue().set("user_1", user);
        User user1 = (User) redisTemplate.opsForValue().get("user_1");
        System.out.println(user1.getName());
    }
}

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

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

相关文章

C++的异常

文章目录 1. C语言传统的处理错误的方式2. C异常概念3. 异常的使用3.1 异常的抛出和匹配原则 4. C标准库的异常体系5. 自定义异常体系6. 异常的重新抛出7. 函数调用链中异常栈展开匹配原则8. 异常安全9. 异常规范10. 异常的优缺点 1. C语言传统的处理错误的方式 传统的错误处理…

【LPC55s69】使用FAL分区管理与easyflash变量管理

文章目录 1.FAL组件1.1什么是FAL1.2 使用ENV配置FAL1.3 FAL SFUD 移植1.4 FAL SFUD 测试用例1.5 测试结果 2.DFS文件系统2.1 什么是DFS2.2 DFS架构2.3 使用ENV配置DFS2.4 DFS挂载到FAL分区测试2.5 测试结果 3.Easyflash移植到FAL分区3.1 简述EasyFlash3.2EasyFlash软件包使用3.…

windows 文件夹目录过长超过长度259字符 文件打不开

当路径超过260个字符时&#xff0c;Windows操作系统就无法处理文件或文件夹&#xff0c;并且无法打开或重命名。这是因为Windows系统使用的文件系统&#xff0c;即FAT和NTFS文件系统&#xff0c;都有最大路径限制。NTFS文件系统最大长度限制为32767个字符&#xff0c;但操作系统…

凝心聚力,携“源”出海:开源社顾问委员会2023年第一季度会议圆满举办!

2023 年 3 月 25 日&#xff0c;开源社顾问委员会&#xff08;以下简称"顾问委员会"&#xff09;第一季度会议在北京圆满召开。这是顾问委员会自 2018 年成立以来的第 17 次全体委员会议。 为增进顾问委员会成员交流&#xff0c;加强开源社社区建设&#xff0c;实现开…

ansible自动运维——ansible使用临时命令通过模块来执行任务

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

制冷暖通工业互联网平台建设

制冷暖通工业互联网平台建设需要遵循一定的流程&#xff0c;具体步骤如下&#xff1a; 需求分析&#xff1a;了解客户需求&#xff0c;包括业务流程、系统功能、界面设计等方面。 系统设计&#xff1a;基于需求分析&#xff0c;进行系统设计&#xff0c;包括系统结构、数据库设…

jekyll+GithubPage搭建一个免费的个人网站

文章目录 Jekyll环境搭建windows安装RUBY、gem、Jekyll用Jekyll搭建本地博客 用jekyll模板搭建githubpage Jekyll环境搭建 windows安装RUBY、gem、Jekyll 安装ruby RUBY安装包下载地址&#xff1a;https://rubyinstaller.org/downloads/&#xff0c;一路默认选项next即可。 最…

LightGBM

LightGBM LightGBM是XGBoost的优化。 提出算法的原因&#xff1a; GBDT在每一次迭代的时候&#xff0c;都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小&#xff1b;如果不装进内存&#xff0c;反复地读写训练数据又会消耗非常大的时间。尤其面…

python 第一章——简介与环境搭建

文章目录 前言一、什么是编程语言二、下载python解释器三、安装pycharm 前言 本系列教程目录可点击这里查看&#xff1a;python教程目录 python在当今世界的流行度应该已经不用我多说了&#xff0c;这可以从TIOBE的榜单中可窥一二 作为一门面向编程新人的语言&#xff0c;它…

matlab数据归一化与反归一化处理

假如数据实际取值范围为 X i ∈ [ − π π ] , i 1 , 2 , 3 X_i \in [-\pi \ \ \pi], i1,2,3 Xi​∈[−π π],i1,2,3&#xff0c;变量服从正态分布 示例如下&#xff1a; %% 数据归一化处理及其概率密度函数 clear clc Mu [0 0 0]; % 均值 Sigma [1 1 1]; % 标准差 C…

水羊转债,超达转债,晓鸣转债上市价格预测

水羊转债 基本信息 转债名称&#xff1a;水羊转债&#xff0c;评级&#xff1a;A&#xff0c;发行规模&#xff1a;6.94987亿元。 正股名称&#xff1a;水羊股份&#xff0c;今日收盘价&#xff1a;13.94元&#xff0c;转股价格&#xff1a;13.71元。 当前转股价值 转债面值 /…

【Leetcode每日一刷】动态规划:509. 斐波那契数、322. 零钱兑换、300. 最长递增子序列

博主简介&#xff1a;努力学习的22级计科生博主主页&#xff1a; 是瑶瑶子啦所属专栏: LeetCode每日一题–进击大厂 前言&#xff1a;动规五部曲 以下是《代码随想录》作者总结的动规五部曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式&#xff0…

ChatGPT写小论文

ChatGPT写小论文 只是个人对写小论文心得?从知乎,知网自己总结的,有问题,可以留个言我改一下 文章目录 ChatGPT写小论文-1.写论文模仿实战(狗头)0.论文组成1.好论文前提:2.标题3.摘要4.关键词5.概述6.实验数据、公式或者设计7.结论&#xff0c;思考8.参考文献 0.模仿1.喂大纲…

【轴承故障检测】滚动轴承中进行基于振动的故障诊断研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

学习笔记-主成分分析法

定义 主成分分析是一种降维算法&#xff0c;它能将多个指标转换为少数几个主成分&#xff0c;这些主成分是原始变量的线性组合&#xff0c;且彼此之间互不相关&#xff0c;其能反映出原始数据的大部分信息。一般来说&#xff0c;当研究的问题涉及到多变量且变量之间存…

人机交互有哪些SCI期刊推荐? - 易智编译EaseEditing

以下是几个人机交互领域的SCI期刊推荐&#xff1a; ACM Transactions on Computer-Human Interaction (ACM TOCHI)&#xff1a; 由ACM&#xff08;Association for Computing Machinery&#xff09;出版的人机交互领域的顶级期刊之一&#xff0c;发表关于计算机和人之间相互作…

如何以产品经理思维打造一所高品质学校?

学校的建设与管理真不是一件容易事。2023年03月17日&#xff0c;山东菏泽市曹县一家长投诉某中学课业繁重&#xff0c;孩子经常写作业到半夜&#xff1b;2023年4月4日&#xff0c;张先生在华龙网重庆网络问政平台投诉万州区某中学伙食差&#xff0c;指出“发灰的洋葱&#xff0…

【21】核心易中期刊推荐——人工智能 | 遥感图像识别

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

023:Mapbox GL加载mp4视频文件

第023个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中加载MP4视频文件。一个视频源。 “urls”值是一个数组。 对于数组中的每个 URL,将创建一个视频元素源。 要支持跨浏览器的视频,请提供多种格式的 URL。“坐标”数组包含按顺时针顺序列出的视频角的 [longi…

如何在 Java 8 中使用 Streams?结合多种案例剖析学习!

Java 8 Streams 是一个非常强大的功能&#xff0c;它提供了一种简洁、优雅的方式来处理数据集合。通过使用 Streams&#xff0c;我们可以轻松地过滤、映射、排序、聚合等操作数据。本教程将介绍 Streams 的基本概念&#xff0c;以及如何在 Java 8 中使用 Streams。本教程还包括…