JavaEE高阶---Redis

news2024/11/16 7:55:59

一:缓存简介

1.1 缓存定义

缓存是一个高速数据交换的存储器,使用它可以快速的访问和操作数据 .

1.2 程序中的缓存

当没有使用缓存时 :

在这里插入图片描述

但随着业务的发展,公司的框架慢慢变成了多个程序调用一个数据库的情况了:

在这里插入图片描述

这是大部分公司的普遍的架构流程图,因此当公司业务发展到一定规模之后,最可能出现性能瓶颈的地方就是数据库。数据库的资源同时也是程序中最昂贵的资源,因此为了防止数据库被过度的浪费,我们就需要给它雇一个“助理”了,这个助理就是缓存系统。

加入缓存后,程序的交互流程如下图所示:

在这里插入图片描述

改进之后 , 当有程序访问数据库时 , 会先向缓存中请求数据 , 如果缓存中有要请求的数据 , 就不需要访问数据库了 ; 当缓存中没有数据时 , 才会访问数据库 , 这样大大降低了数据库的压力 , 同时也提高了程序的反应速度 .

在这里插入图片描述

1.3 缓存优点

相比于数据库而言,缓存的操作性能更高,缓存性能高的主要原因有以下几个:

  1. 缓存一般都是 key-value 查询数据的,因为不像数据库一样还有查询的条件等因素,所以查询的性能一般会比数据库高;
  2. 缓存的数据是存储在内存中的,而数据库的数据是存储在磁盘中的,因为内存的操作性能远远大于磁盘,因此缓存的查询效率会高很多;
  3. 缓存更容易做分布式部署(当一台服务器变成多台相连的服务器集群),而数据库一般比较难实现分布式部署,因此缓存的负载和性能更容易平行扩展和增加。

1.4 缓存分类

缓存可分为本地缓存和分布式缓存 .

本地缓存也叫单机缓存,也就是说可以应用在单机环境下的缓存。所谓的单机环境是指,将服务部署到一台服务器上,如下图所示 :

在这里插入图片描述

举个栗子

本地缓存相当于学校的规定 , 每个学校有不同的规定 , 例如熄灯时间 , 西科大晚上23点熄灯 , 西石油晚上12点熄灯, 西交大晚上直接不熄灯 . 对于学校的规定 , 只适用于本校 .

同样地 , 本地缓存的特征是只适用于当前系统 .


分布式缓存是指可以应用在分布式系统中的缓存。所谓的分布式系统是指将一套服务部署到多台服务器,并且通过负载分发将用户的请求按照一定的规则分发到不同服务器,如下图所示 :

在这里插入图片描述

举个栗子

分布式系统相当于国家的规定 , 例如非法种植罂粟三千株以上或者其他毒品原植物数量大的,处五年以上有期徒刑,并处罚金或者没收财产。作为中国公民 , 都应当遵守这样的规定 .

分布式缓存就适用于所有的系统 . 比如我们在分布式系统中的服务器 A 中存储了一个缓存 key=laobai,那么在服务器 B 中也可以读取到key=laobai 的数据,这就是分布式缓存的作用 .

1.5 常见缓存使用

本地缓存的常见使用:Spring Cache、MyBatis 的缓存等。

分布式缓存的常见使用:Redis 和 Memcached。

1.5.1 本地缓存—Spring Cache

在 Spring Boot 项目,可以直接使用 Spring 的内置 Cache(本地缓存),只需要完成以下三个步骤就可以正常使用了:

  • 开启缓存
  • 操作缓存
  • 调用缓存

1.开启缓存 : 在 Spring Boot 的启动类上添加如下代码,开启缓存:

@SpringBootApplication
@EnableCaching # 开启缓存功能
public class BiteApplication {
	public static void main (String[] args) {
  		SpringApplication run BiteApplication class args
	}
}

2.编写缓存操作代码 : 在 Service 层增加三个缓存操作的方法:添加缓存、修改缓存、删除缓存,示例代码如下:

package com.example.demo.service;

import com.example.demo.model.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    //查询用户信息[走缓存]
    @Cacheable(cacheNames = "getuser",key = "#id")
    public User getUserId(int id) {
        System.out.println("进入getUserId方法~~");
        User user = new User();
        user.setId(id);
        user.setName("Java");
        user.setPassword("123456");
        return user;
    }
    //修改用户信息
    @Cacheable(cacheNames = "getuser",key="#id")
    public User updateUser(int id,String name,String password) {
        System.out.println("进入updateUser方法~~");
        User user = new User();
        user.setId(id);
        user.setName(name);
        user.setPassword(password);
        return user;
    }
    //删除用户信息
    @Cacheable(cacheNames = "getuser",key="#id")
    public boolean delUser(int id) {
        System.out.println("进入delUser方法~~");
        return true;
    }
}

3.编写触发代码

package com.example.demo.controller;

import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/getuser")
    public User getUserId(int id) {
        return userService.getUserId(id);
    }

    @RequestMapping("/update")
    public User updateUser(int id,String name,String password) {
        return userService.updateUser(id,name,password);
    }

    @RequestMapping("/del")
    public boolean delUser(int id) {
        return userService.delUser(id);
    }
}

以上步骤执行完之后,可以使用 Postman 模拟调用来查看缓存 .

1.5.2 分布式缓存—Redis

在 Spring 框架中我们也可以直接操作 Redis 缓存,它的操作流程如下图所示:

在这里插入图片描述

Q : Redis 和 Memcached 有什么区别?

A :

  • 存储方式不同:memcache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小;Redis 有部分存在硬盘上,这样能保证数据的持久性;
  • 数据支持类型:memcache 对数据类型支持相对简单;Redis 有复杂的数据类型;
  • 存储值大小不同:Redis 最大可以达到 512MB,memcache 只有 1MB。

总结:通常情况下,如果是单机 Spring 项目,会直接使用 Spring Cache 作为本地缓存,如果是分布式环境一般会使用 Redis。

二 : Redis

REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库。

2.1 Redis数据类型和使用

Redis 有 5 大基础数据类型:

  • String——字符串类型
  • Hash——字典类型
  • List——列表类型
  • Set——集合类型
  • ZSet——有序集合类型

其中最常用的是字符串和字典类型。

2.1.1 字符串类型

字符串类型 ( Simple Dynamic Strings) , 简称 SDS ,译为:简单动态字符串,它是以键值对 key-value 的形式进行存储的,根据 key 来存储和获取 value 值,它的使用相对来说比较简单,但在实际项目中应用非常广泛。

字符串的使用 :

在这里插入图片描述

注意 , 第一个命令来了 , 使用下面的命令可以连接Redis服务器 :

redis-cli

我们也可以使用 ex(expires)参数来设置字符串的过期时间,如下代码所示:

在这里插入图片描述

设置key3 1000s后过期 .

字符串的常见使用场景:

  • 存放用户(登录)信息;

  • 存放文章详情和列表信息;

  • 存放和累计网页的统计信息。

2.1.2 字典类型

字典类型 (Hash) 又被称为散列类型或者是哈希表类型,它是将一个键值 (key) 和一个特殊的“哈希表”关联起来,这个“哈希表”表包含两列数据:字段和值,它就相当于 Java 中的
Map<String,Map<String,String>>
结构。

假如我们使用字典类型来存储一篇文章的详情信息,存储结构如下图所示:

在这里插入图片描述

在这里插入图片描述

字典类型的数据结构,如下图所示:

在这里插入图片描述

通常情况下字典类型会使用数组的方式来存储相关的数据,但发生哈希冲突时才会使用链表的结构来存储数据。

2.2 持久化

所谓的持久化就是将数据从内存保存到磁盘的过程,它的目的就是为了防止数据丢失 。因为内存中的数据在服务器重启之后就会消失 , 而磁盘的数据则不会,因此为了系统的稳定起见,我们需要将数据进行持久化。同时持久化功能又是 Redis 和 Memcached 最主要的区别之一,因为 Redis 支持持久化而 Memcached 不支持 .

Redis持久化的方式有以下3种 :

  1. 快照方式(RDB,Redis DataBase)将某一个时刻的内存数据,以二进制的方式写入磁盘;
  2. 文件追加方式(AOF,Append Only File),记录所有的操作命令,并以文本的形式追加到文件中;
  3. 混合持久化方式,Redis 4.0之后新增的方式,混合持久化是结合了RDB和AOF的优点,在写入的时候,先把当前的数据以RDB的形式写入文件的开头,再将后续的操作命令以AOF的格式存入文件,这样既能保证 Redis重启时的速度,又能降低数据丢失的风险。

2.2.1 RDB优点

RDB 的内容为二进制的数据,占用内存更小,更紧凑,更适合做为备份文件;

RDB对灾难恢复非常有用,它是一个紧凑的文件,可以更快的传输到远程服务器进行Redis服务恢复;

RDB可以更大程度的提高Redis 的运行速度,因为每次持久化时Redis 主进程都会fork()一个子进程,进行数据持久化到磁盘,Redis主进程并不会执行磁盘l/O等操作;与AOF格式的文件相比,RDB文件可以更快的重启。

2.2.2 RDB缺点

因为RDB只能保存某个时间间隔的数据,如果中途Redis服务被意外终止了,则会丢失一段时间内的Redis数据;

RDB需要经常 fork()才能使用子进程将其持久化在磁盘上。如果数据集很大,fork()可能很耗时,并且如果数据集很大且CPU性能不佳,则可能导致Redis 停止为客户端服务几毫秒甚至一秒钟。

2.2.3 AOF优点

AOF持久化保存的数据更加完整,AOF提供了三种保存策略︰

  • 每次操作保存
  • 每秒钟保存一次
  • 跟随系统的持久化策略保存

其中每秒保存一次,从数据的安全性和性能两方面考虑是一个不错的选择,也是AOF默认的策略,即使发生了意外情况,最多只会丢失1s 钟的数据;

AOF采用的是命令追加的写入方式,所以不会出现文件损坏的问题,即使由于某些意外原因,导致了最后操作的持久化数据写入了一半,也可以通过redis-check-aof工具轻松的修复;

AOF持久化文件,非常容易理解和解析,它是把所有Redis键值操作命令,以文件的方式存入了磁盘。即使不小心使用flushall命令删除了所有键值信息,只要使用AOF文件,删除最后的flushall命令,重启Redis 即可恢复之前误删的数据。

2.2.4 AOF缺点

对于相同的数据集来说,AOF文件要大于RDB文件;

在Redis 负载比较高的情况下,RDB 比 AOF性能更好;

RDB使用快照的形式来持久化整个Redis 数据,而AOF 只是将每次执行的命令追加到AOF 文件中,因此从理论上说,RDB 比AOF更健壮。

( 健壮性具体指的是系统在不正常的输入或不正常的外部环境下仍能表现出正常的程度.)

2.2.5 混合持久化优点

混合持久化结合了RDB 和AOF持久化的优点,开头为RDB 的格式,使得Redis可以更快的启动,同时结合AOF 的优点,有效降低了大量数据丢失的风险。

2.2.6 混合持久化缺点

AOF文件中添加了RDB格式的内容,使得AOF文件的可读性变得很差;

兼容性差,如果开启混合持久化,那么此混合持久化AOF文件,就不能用在Redis 4.0之前版本了。

2.3 安装Redis

2.3.1 yum安装Redis

使用命令行方式安装Redis . 使用以下命令,直接将 redis 安装到 linux 服务器:

yum -y install redis

在这里插入图片描述

显示Complete! 即表示安装成功了 !

2.3.2 启动Redis

使用以下方式 , 以后台运行方式启动redis :

redis-server /etc/redis.conf &

在这里插入图片描述

使用下列命令可以查看redis进程 :

ps -ef|grep redis

2.3.3 操作Redis

使用以下命令启动 redis 客户端:

redis-cli

2.3.4 设置远程连接

  1. 将 redis 配置文件下载到本地:redis 配置文件是 linux 下的 /etc/redis.conf ;
  2. 将 redis.conf 中的 “bind 127.0.0.1”注释掉;
  3. 将 redis.conf 中的“protected-mode yes” 改为“protected-mode no”;
  4. 将修改后的 redis.conf 上传至 liunx 下的 /etc 目录;
  5. 使用命令“redis-cli shutdown”先关闭 redis 服务,再使用“redis-server /etc/redis.conf &”启动 redis 服务 .

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用 Another Redis Desktop Manager 查看连接效果 :

在这里插入图片描述

顺便说一下 , Redis的默认端口是6379 , 但是后来我的6379端口出现了安全性问题 , 所以我将Redis的端口改到了6378(在配置文件中修改即可) .

2.4 SpringBoot集成Redis

2.4.1 添加Redis依赖

在这里插入图片描述

2.4.2 配置 redis

spring.redis.database=1
spring.redis.port=6378
spring.redis.host=121.4.87.61
spring.session.store-type=redis
server.servlet.session.timeout=1800
spring.session.redis.flush-mode=on_save
spring.session.redis.namespace=spring:session

在这里插入图片描述

2.4.3 操作Redis

package com.example.demo.controller;
import com.example.demo.model.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RedisController {

    private User user;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    private final String object_redis_key ="user1";

    private final String object_redis_key2 ="user2";


    //在Redis中存储字符串
    @RequestMapping("/setstr")
    public String setRedis(String key,String value) {
        if(StringUtils.hasLength(key) && StringUtils.hasLength(value)) {
            stringRedisTemplate.opsForValue().set(key,value);
            return "Redis设置成功!";
        } else {
            return "参数有误!";
        }
    }

    //读取Redis中的字符串
    @RequestMapping("/getstr")
    public String getRedis(String key) {
        String value = null;
        if(StringUtils.hasLength(key)) {
            value = stringRedisTemplate.opsForValue().get(key);
        }
        return "结果是: " + value;
    }

    //单例模式
    public User getUser() {
        if(user == null) {
            synchronized (this) {
                if(user == null) {
                    user = new User();
                    user.setId(1);
                    user.setName("白居易");
                    user.setPassword("123456");
                }
            }
        }
        return user;
    }

    //将对象存储到 redis
    @RequestMapping("/setobj")
    public String setObj() throws JsonProcessingException {
        User user = getUser();
        System.out.println(user);
        String userStr = objectMapper.writeValueAsString(user);
        stringRedisTemplate.opsForValue().set(object_redis_key, userStr);
        return "操作成功!";
    }

    @RequestMapping("/getobj")
    public User getObj() throws JsonProcessingException {
        String userStr = (String) stringRedisTemplate.opsForValue().get(object_redis_key);

        User user = objectMapper.readValue(userStr, User.class);
        return user;
    }


    //将对象存储到 redis hash 中
    @RequestMapping("/sethash")
    public boolean setHash() {
        User user = getUser();
        stringRedisTemplate.opsForHash().put(object_redis_key2, "id", String.valueOf(user.getId()));
        stringRedisTemplate.opsForHash().put(object_redis_key2, "name", user.getName());
        stringRedisTemplate.opsForHash().put(object_redis_key2, "password", user.getPassword());
        return true;
    }

    @RequestMapping("/gethash")
    public String getHash() {
        return stringRedisTemplate.opsForHash().get(object_redis_key2, "name").toString();
    }

}

存储字符串 :

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
存储对象 :

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

存储字典类型 :

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.5 Spring Session持久化

2.5.1 添加依赖

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

2.5.2 修改配置

spring.redis.database=2
spring.redis.port=6378
spring.redis.host=121.4.87.61
spring.session.store-type=redis
server.servlet.session.timeout=1800
spring.session.redis.flush-mode=on_save
spring.session.redis.namespace=spring:session

Redis默认16个db , 此处使用数据库2 . 对于db正确的理解应为“命名空间”,多个应用程序不应使用同一个Redis不同库,而应一个应用程序对应一个Redis实例,不同的数据库可用于存储不同环境的数据。关于为什么Redis默认16个库, 可以参考这篇文章 .

2.5.3 存储和读取代码

package com.example.demo.model;
import lombok.Data;
import java.io.Serializable;

@Data
public class User implements Serializable {
    public int id;
    public String name;
    public String password;
}

注意进行序列化 !

在这里插入图片描述

package com.example.demo.controller;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@RestController
public class UserController {

    private String user_session_key = "session1";
    
    @RequestMapping("/login")
    public boolean login(HttpSession session) {
        User user = new User();
        user.setId(2);
        user.setName("张三");
        user.setPassword("123456");
        session.setAttribute(user_session_key,user);
        return true;
    }

    @RequestMapping("/getsession")
    public User getSession(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if(session != null) {
            return (User) session.getAttribute(user_session_key);
        }
        return null;
    }

}

在这里插入图片描述

会话信息是否缓存了呢 ? 借助工具查看 :

在这里插入图片描述

这时候调用getsession :

在这里插入图片描述

此时重启IDEA , 如果用户信息被缓存 , 那么再次调用getsession , 应该还是可以得到同样的信息 :

在这里插入图片描述

这就是使用Redis进行session持久化的整个过程 !

2.6 Redis相关面试题

参考文章 : Redis相关面试题

2.7 改进博客项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改完毕 !!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设备加密狗

场景描述 随着科技的飞速发展&#xff0c;越来越多的智能设备走进生产加工车间。例如智能雕刻机、钣金机、榫槽机、钻孔机、磨刀机等等。 这些智能设备存在很大共性&#xff0c;就是都内嵌完整的操作系统。有的是windows&#xff0c;有的是linux。设备制造商提供的专业软件运…

pycharm的下载讲解以及安装步骤

目录 Python安装 这时&#xff0c;有人要问了&#xff0c;下载pycharm一定要下载Python么&#xff1f; Python官网 Pycharm安装 完成 推荐书籍 写在最后 Python安装 首先我们进入Python的官方下载网站 这时&#xff0c;有人要问了&#xff0c;下载pycharm一定要下载Py…

算法设计与分析期末考试复习(五)

回溯法 回溯法是一种试探法&#xff0c;将n元问题P的状态空间E表示成为一棵高为n的带权有序数T&#xff0c;把在E中求问题P的解转换为在T中搜索问题P的解。 解题方法&#xff1a;按选优条件对T进行深度优先搜索&#xff0c;以达到目标。 从根节点出发深度优先搜索解空间树。当…

初学网络安全不可不知的:10款开源安全工具

随着互联网的不断发展&#xff0c;安全问题也越来越受到企业的重视。但安全问题往往需要大量资金的投入&#xff0c;例如聘请安全工程师&#xff0c;产品研发&#xff0c;测试等流程。这对于那些原本就资金紧缺的企业而言&#xff0c;是绝对无法接受的。因此&#xff0c;为了减…

Python3+Selenium3自动化测试-(准备)

最近在学习selenium自动化测试相关的内容&#xff0c;所以将实际准备情况做一记录&#xff0c; # 系统&#xff1a;win10(64位) # 浏览器&#xff1a;Chrome(67.0)、Firefox(61.0)、IE # python版本&#xff1a;3.6.5 # Selenium&#xff1a;3.13.0Selenium简介 Selenium是一…

JUC并发编程——线程安全问题

目录一、共享问题1.1 共享带来的问题1.2 临界区与竞态条件二、解决方案2.1 上下文切换——synchronized-解决2.2 上下文切换——synchronized-理解2.3 上下文切换——synchronized-思考2.4 锁面向对象改进2.5 方法上的 synchronized三、synchronized习题3.1 synchronized-加在方…

记住这些快捷键,让你轻松玩转mac(macOS 常用快捷键分享)

适当运用键盘快捷键可以帮助用户提高效率&#xff0c;这里小编为大家带来了一些macOS 常用快捷键&#xff0c;掌握这些快捷键可以帮你解放鼠标手&#xff0c;成为键盘侠&#xff0c;一起来看看吧&#xff01; 快捷键标识简介 当你在应用菜单中发现部分操作项后边有一些特殊标…

搜广推 AutoRec与 Deep Crossing - 推荐系统深度学习模型开篇

😄 AutoRec:2015年由澳大利亚国立大学提出。【后文简称AR】 😄 DeepCrossing:2016年,微软基于ResNet的经典DNN结构。【后文简称DC】 文章目录 1、AutoRec1.1、原理1.2、优点1.3、缺点2、Deep Crossing2.1、原理2.2、优点:2.3、缺点:Reference1、AutoRec 1.1、原理 -…

IEEE SLT 2022论文丨如何利用x-vectors提升语音鉴伪系统性能?

分享一篇IEEE SLT 2022收录的声纹识别方向的论文&#xff0c;《HOW TO BOOST ANTI-SPOOFING WITH X-VECTORS》由AuroraLab&#xff08;极光实验室&#xff09;发表。 来源丨AuroraLab AuroraLab源自清华大学电子工程系与新疆大学信息科学与工程学院&#xff0c;以说话人识别和…

Qt 第9课、计算器中缀转后缀算法

计算器核心算法&#xff1a; 1、将中缀表达式进行数字和运算符的分离 2、将中缀表达式转换成后缀表达式 3、通过后缀表达式计算最后的结果 二、计算器中缀转后缀算法 计算器中缀转后缀算法的意义在于把中缀表达式转换成后缀表达式&#xff0c;能够更好地计算 算法的基本思路…

【RabbitMQ笔记08】消息队列RabbitMQ之防止消息丢失的三种方式(生产者消息确认、消费者消息确认、消息持久化)

这篇文章&#xff0c;主要介绍消息队列RabbitMQ之防止消息丢失的三种方式&#xff08;生产者消息确认、消费者消息确认、消息持久化&#xff09;。 目录 一、防止消息丢失 1.1、消息确认机制&#xff08;生产者&#xff09; &#xff08;1&#xff09;生产者丢失消息 &…

字节跳动软件测试岗4轮面经(已拿34K+ offer)...

没有绝对的天才&#xff0c;只有持续不断的付出。对于我们每一个平凡人来说&#xff0c;改变命运只能依靠努力幸运&#xff0c;但如果你不够幸运&#xff0c;那就只能拉高努力的占比。 2021年10月&#xff0c;我有幸成为了字节跳动的一名测试工程师&#xff0c;从外包辞职了历…

一文读懂自动驾驶运行设计域ODD

/ 导读 /在自动驾驶技术发展如此迅速的今天&#xff0c;很多量产车上已经配备了多种的辅助驾驶功能&#xff0c;例如自适应巡航ACC、紧急制动AEB、车道居中保持LKA等等&#xff0c;很多的车主也都体验到了技术带给驾驶的改变。另一方面&#xff0c;由于现在的自动驾驶技术还处于…

量化选股——基于动量因子的行业风格轮动策略(第2部分—策略回测)

文章目录1. 交易策略2. Backtrader回测程序3. 回测效果3.1 2020年1月1日 - 2021年1月1日3.2 2021年1月1日 — 2022年1月1日3.3 2022年1月1日 — 2023年1月1日动量因子的概述与测算&#xff0c;阿隆指标测算请参考&#xff1a;https://blog.csdn.net/weixin_35757704/article/de…

react源码解析1.开篇介绍和面试题

怎样学习react源码 作为前端最常用的js库之一&#xff0c;熟悉react源码成了高级或资深前端工程师必备的能力&#xff0c;如果你不想停留在api的使用层面或者想在前端技能的深度上有所突破&#xff0c;那熟悉react源码将是你进步的很好的方式。 react的纯粹体现在它的api上&a…

【神经网络】LSTM

1.什么是LSTM 长短期记忆&#xff08;Long short-term memory, LSTM&#xff09;是一种特殊的RNN&#xff0c;主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题。简单来说&#xff0c;相比普通的RNN&#xff0c;LSTM能够在更长的序列中有更好的表现。 LSTM区别于RNN地方…

Java查漏补缺(09)异常概述、Java异常体系、常见的错误和异常、异常的处理、手动抛出异常对象:throw、自定义异常

Java查漏补缺&#xff08;09&#xff09;异常概述、Java异常体系、常见的错误和异常、异常的处理、手动抛出异常对象&#xff1a;throw、自定义异常本章专题与脉络1. 异常概述1.1 什么是生活的异常1.2 什么是程序的异常1.3 异常的抛出机制1.4 如何对待异常2. Java异常体系2.1 T…

【JAVA】xxl-job服务搭建

xxl-job服务搭建 1.下载xxl-job项目 https://github.com/xuxueli/xxl-job 2.数据库表创建 3.修改配置 注意&#xff1a;这是两个项目&#xff0c;一个是xxl-job前台&#xff0c;一个是xxl-job执行器&#xff0c;找到这两个项目得配置文件&#xff0c;修改配置。 配置文件地址…

day54【代码随想录】二刷数组

文章目录前言一、二分查找&#xff08;力扣724&#xff09;二、移除元素&#xff08;力扣27&#xff09;【双指针】三、有序数组的平方&#xff08;力扣977&#xff09;【双指针】四、合并两个有序数组&#xff08;力扣88&#xff09;五、长度最小的子数组&#xff08;力扣209&…

前端学习第二阶段-第3章 Flex 伸缩布局

3-1 移动端基础知识 01-移动端基础 02-视口 03-meta视口标签 04-物理像素与物理像素比 05-二倍图 06-背景缩放background-size 07-背景二倍图以及多倍图切图 08-移动端开发选择 09-移动端技术解决方案 10-移动端特殊样式 11-移动端技术选型 12-流式布局 3-2 移动端电商首页制作…