Redis学习——高级篇⑨

news2024/11/18 20:01:07

Redis学习——高级篇⑨

    • = = = = = = = Redis7高级之Redlock算法和Redisson的使用(十) = = = = = = =
    • 10.1 Redlock 红锁算法
      • 1.解决手写分布式锁的单点故障问题
      • 2.设计理念
      • 3. 解决方案
    • 10.2 Redisson进行代码改造
    • 10.3 多机案例(解决单点故障)
    • 10.4 Redis 的缓存淘汰策略
      • 1.Redis 内存满了怎么办?
      • 2.Redis 过期键的删除策略
      • 3.redis 缓存淘汰策略
        • 3.1 LRU 和 LFU
        • 3.2 8种缓存淘汰策略
      • 4.性能配置建议

在这里插入图片描述

在这里插入图片描述
lock加锁关键逻辑

  1. 加锁的Lua脚本,通过redis 里面的hash数据模型,加锁和可重入性都要保证
  2. 加锁不成,需要while进行重试并自旋.
  3. 自动续期,加个钟

在这里插入图片描述

unlock解锁关键逻辑

  1. 考虑可重入性的递减,加锁几次就要减锁几次
  2. 最后到零了,直接del删除

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

= = = = = = = Redis7高级之Redlock算法和Redisson的使用(十) = = = = = = =

在这里插入图片描述

10.1 Redlock 红锁算法

1.解决手写分布式锁的单点故障问题

  • Redis 提供了 Redlock 算法,用来实现基于多个实例的分布式锁
  • 锁变量由多个实例维护,即使有实例发生了故障,锁变量仍然是存在的,客户端还是可以完成锁操作
  • Redlock算法是实现高可靠分布式锁的一种有效解决方案,可以在实际开发中使用

红锁算法

在算法的分布式版本中,我们假设我们有N个Redis主节点。这些节点是完全独立的,所以我们不使用复制或任何其他隐式协调系统。我们已经描述了如何在单个实例中安全地获取和释放锁。我们想当然地认为算会使用这个方法在单个实例中获取和释放锁。在我们的示例中,我们设置N=5,这是一个合理的值,因此我们需要在不同的计算机或虚拟机上运行5个Redis master,以确保它们以几乎独立的方式发生故障

为了获取锁,客户端执行以下操作:

  1. 它以毫秒为单位获取当前时间。
  2. 它尝试在所有N个实例中顺序获取锁,在所有实例中使用相同的键名和随机值。在步骤2中,在每个实例中设置锁时,客户端使用与总锁自动释放时间相比较小的超时来获取锁。例如,如果自动释放时间为10秒,则超时可能在5-50毫秒范围内。这可以防止客户端在尝试与已关闭的Redis节点通信时长时间处于阻塞状态:如果一个实例不可用, 我们应该尽快尝试与下一个实例通信。
  3. 客户端通过从当前时间减去步骤1中获得的时间戳来计算获得锁所用的时间。当且仅当客户端能够在大多数实例(至少3个)中获得锁时,并且获得锁的总时间小于锁有效期,则认为获得了锁。
  4. 如果获得了锁,则其有效时间被认为是初始有效时间减去经过的时间,如步骤3中计算的那样。
  5. 如果客户端由于某种原因未能获得锁(要么无法锁定 N / 2 + 1 N/2+1 N/2+1个实例,要么有效期为负),它将尝试解锁所有实例(即使是它认为不能锁定的实例)可以锁定)

2.设计理念

假设我们有N个Redis主节点,例如 N = 5 N = 5 N=5这些节点是完全独立的,我们不使用复制或任何其他隐式协调系统,为了取到锁客户端执行以下操作:

1获取当前时间,以毫秒为单位;
2依次尝试从5个实例,使用相同的 key 和随机值(例如 UUID)获取锁。当向Redis 请求获取锁时,客户端应该设置一个超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为 10 秒,则超时时间应该在 5-50 毫秒之间。这样可以防止客户端在试图与一个宕机的 Redis 节点对话时长时间处于阻塞状态。如果一个实例不可用,客户端应该尽快尝试去另外一个 Redis 实例请求获取锁;
3客户端通过当前时间减去步骤 1 记录的时间来计算获取锁使用的时间。当且仅当从大多数(N/2+1,这里是 3 个节点)的 Redis 节点都取到锁,并且获取锁使用的时间小于锁失效时间时,锁才算获取成功;
4如果取到了锁,其真正有效时间等于初始有效时间减去获取锁所使用的时间(步骤 3 计算的结果)。
5如果由于某些原因未能获得锁(无法在至少 N / 2 + 1 N/2 + 1 N/2+1 个 Redis 实例获取锁、或获取锁的时间超过了有效时间),客户端应该在所有的 Redis 实例上进行解锁(即便某些Redis实例根本就没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时间不能被重新获取锁)。

该方案为了解决数据不一致的问题,直接舍弃了异步复制只使用 master 节点,同时由于舍弃了 slave,为了保证可用性,引入了 N 个节点,官方建议是 5。

客户端只有在满足下面的这两个条件时,才能认为是加锁成功。

条件1:客户端从超过半数(大于等于N/2+1)的Redis实例上成功获取到了锁;

条件2:客户端获取锁的总耗时没有超过锁的有效时间。

3. 解决方案

在这里插入图片描述

为什么是奇数? N = 2X + 1 (N是最终部署机器数,X是容错机器数)

1 先知道什么是容错

失败了多少个机器实例后我还是可以容忍的,所谓的容忍就是数据一致性还是可以Ok的,CP数据一致性还是可以满足

加入在集群环境中,redis失败1台,可接受。2X+1 = 2 * 1+1 =3,部署3台,死了1个剩下2个可以正常工作,那就部署3台。

加入在集群环境中,redis失败2台,可接受。2X+1 = 2 * 2+1 =5,部署5台,死了2个剩下3个可以正常工作,那就部署5台。

2 为什么是奇数?

最少的机器,最多的产出效果

​ 加入在集群环境中,redis失败1台,可接受。2N+2= 2 * 1+2 =4,部署4台

​ 加入在集群环境中,redis失败2台,可接受。2N+2 = 2 * 2+2 =6,部署6台

10.2 Redisson进行代码改造

Redisson 就是 Redlock算法 的实现

  • POM
<!--redisson-->
<dependency>
	 <groupId>org.redisson</groupId>
	 <artifactId>redisson</artifactId>
	 <version>3.13.4</version>
</dependency>
  • RedisConfig
import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
    {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }

//    v 8.0 引入 redisson
    @Bean
    public Redisson redisson() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://192.168.238.111:6379")
                .setDatabase(0)
                .setPassword("123456");
        return (Redisson) Redisson.create(config);
    }
}
  • InventoryController
import com.xfcy.service.InventoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@Api(tags = "redis分布式锁测试")
public class InvetoryController {

    @Autowired
    private InventoryService inventoryService;

    @ApiOperation("扣减库存sale,一次卖一个")
    @GetMapping(value = "/inventory/sale")
    public String sale()
    {
        return inventoryService.sale();
    }


    @ApiOperation("扣减库存saleByRedisson,一次卖一个")
    @GetMapping(value = "/inventory/saleByRedisson")
    public String saleByRedisson()
    {
        return inventoryService.saleByRedisson();
    }
}
  • InventoryService
/**
 * v 9.0    引入Redisson对应的官网推荐RedLock算法实现
 *
 * @return
 */
@Autowired
private Redisson redisson;

public String saleByRedisson() {
    String retMessage = "";

    RLock redissonLock = redisson.getLock("xfcyRedisLock");
    redissonLock.lock();
    try {
        //1 查询库存信息
        String result = stringRedisTemplate.opsForValue().get("inventory001");
        //2 判断库存是否足够
        Integer inventoryNumber = result == null ? 0 : Integer.parseInt(result);
        //3 扣减库存
        if (inventoryNumber > 0) {
            stringRedisTemplate.opsForValue().set("inventory001", String.valueOf(--inventoryNumber));
            retMessage = "成功卖出一个商品,库存剩余: " + inventoryNumber;

        } else {
            retMessage = "商品卖完了,o(╥﹏╥)o";
        }
        System.out.println(retMessage);
    } finally {
        // 改进点,只能删除属于自己的 key,不能删除别人的
        if (redissonLock.isLocked() && redissonLock.isHeldByCurrentThread()){
            redissonLock.unlock();
        }
    }
    return retMessage + "\t" + "服务端口号:" + port;
}

10.3 多机案例(解决单点故障)

使用 Redisson 的 MultiLock 多重锁

  • 使用docker 启动 3 台redis master ,3台master 并无从属关系
docker run -p 6381:6379 --name redis-master-1 -d redis
docker run -p 6382:6379 --name redis-master-2 -d redis
docker run -p 6383:6379 --name redis-master-3 -d redis
  • 进入到redis容器实例
docker exec -it redis-master-1 redis-cli
docker exec -it redis-master-2 /bin/bash 
docker exec -it redis-master-3 /bin/bash  
  • 建 Module redis_redlock

  • POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.atguigu.redis.redlock</groupId>
    <artifactId>redis_redlock</artifactId>
    <version>0.0.1-SNAPSHOT</version>


    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.19.1</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.14</version>
        </dependency>
        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--swagger-ui-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • YML
server.port=9090
spring.application.name=redlock


spring.swagger2.enabled=true


spring.redis.database=0
#没配置密码
spring.redis.password=
spring.redis.timeout=3000
spring.redis.mode=single

spring.redis.pool.conn-timeout=3000
spring.redis.pool.so-timeout=3000
spring.redis.pool.size=10

spring.redis.single.address1=192.168.238.111:6381
spring.redis.single.address2=192.168.238.111:6382
spring.redis.single.address3=192.168.238.111:6383
  • 主启动
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RedisRedlockApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisRedlockApplication.class, args);
    }
}
  • 配置类
  • CacheConfiguration
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class CacheConfiguration {

    @Autowired
    RedisProperties redisProperties;

    @Bean
    RedissonClient redissonClient1() {
        Config config = new Config();
        String node = redisProperties.getSingle().getAddress1();
        node = node.startsWith("redis://") ? node : "redis://" + node;
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(node)
                .setTimeout(redisProperties.getPool().getConnTimeout())
                .setConnectionPoolSize(redisProperties.getPool().getSize())
                .setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle());
        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
            serverConfig.setPassword(redisProperties.getPassword());
        }
        return Redisson.create(config);
    }

    @Bean
    RedissonClient redissonClient2() {
        Config config = new Config();
        String node = redisProperties.getSingle().getAddress2();
        node = node.startsWith("redis://") ? node : "redis://" + node;
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(node)
                .setTimeout(redisProperties.getPool().getConnTimeout())
                .setConnectionPoolSize(redisProperties.getPool().getSize())
                .setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle());
        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
            serverConfig.setPassword(redisProperties.getPassword());
        }
        return Redisson.create(config);
    }

    @Bean
    RedissonClient redissonClient3() {
        Config config = new Config();
        String node = redisProperties.getSingle().getAddress3();
        node = node.startsWith("redis://") ? node : "redis://" + node;
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(node)
                .setTimeout(redisProperties.getPool().getConnTimeout())
                .setConnectionPoolSize(redisProperties.getPool().getSize())
                .setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle());
        if (StringUtils.isNotBlank(redisProperties.getPassword())) {
            serverConfig.setPassword(redisProperties.getPassword());
        }
        return Redisson.create(config);
    }


    /**
     * 单机
     * @return
     */
    /*@Bean
    public Redisson redisson()
    {
        Config config = new Config();

        config.useSingleServer().setAddress("redis://192.168.111.147:6379").setDatabase(0);

        return (Redisson) Redisson.create(config);
    }*/
}
  • RedisPoolProperties
import lombok.Data;

@Data
public class RedisPoolProperties {
    private int maxIdle;

    private int minIdle;

    private int maxActive;

    private int maxWait;

    private int connTimeout;

    private int soTimeout;

    /*
      池大小
     */
    private  int size;
}
  • RedisProperties
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;


@ConfigurationProperties(prefix = "spring.redis", ignoreUnknownFields = false)
@Data
public class RedisProperties {

    private int database;

    /*
    等待节点回复命令的时间。 该时间从命令发送成功时开始计时
     */
    private int timeout = 3000;

    private String password;

    private String mode;

    /*
        池配置
     */
    private RedisPoolProperties pool;

    /*
        单机信息配置
     */
    private RedisSingleProperties single;

}
  • RedisSingleProperties
import lombok.Data;

@Data
public class RedisSingleProperties {

    private String address1;

    private String address2;

    private String address3;
}
  • 业务类
  • RedLockController
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.RedissonMultiLock;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@RestController
@Slf4j
public class RedLockController {

    public static final String CACHE_KEY_REDLOCK = "ATGUIGU_REDLOCK";

    @Autowired
    RedissonClient redissonClient1;

    @Autowired
    RedissonClient redissonClient2;

    @Autowired
    RedissonClient redissonClient3;

    boolean isLockBoolean;

    @GetMapping(value = "/multiLock")
    public String getMultiLock() throws InterruptedException
    {
        String uuid =  IdUtil.simpleUUID();
        String uuidValue = uuid+":"+Thread.currentThread().getId();

        RLock lock1 = redissonClient1.getLock(CACHE_KEY_REDLOCK);
        RLock lock2 = redissonClient2.getLock(CACHE_KEY_REDLOCK);
        RLock lock3 = redissonClient3.getLock(CACHE_KEY_REDLOCK);

        RedissonMultiLock redLock = new RedissonMultiLock(lock1, lock2, lock3);
        redLock.lock();
        try
        {
            System.out.println(uuidValue+"\t"+"---come in biz multiLock");
            try { TimeUnit.SECONDS.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println(uuidValue+"\t"+"---task is over multiLock");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("multiLock exception ",e);
        } finally {
            redLock.unlock();
            log.info("释放分布式锁成功key:{}", CACHE_KEY_REDLOCK);
        }
        return "multiLock task is over  "+uuidValue;
    }
}
  • 测试

    • 就是在发送请求时,模拟一台机器挂掉,查看系统是否还能运行

10.4 Redis 的缓存淘汰策略

1.Redis 内存满了怎么办?

  • 查看 Redis 最大占用内存

在这里插入图片描述

  • redis默认内存多少

    • 如果在 64位操作系统, maxmemory 设置0或者不设置最大内存大小表示不限制Redis内存使用
  • 一般生产上如何配置

    • 推荐Redis设置为最大物理内存的四分之三

如何修改redis内存设置

  • 通过配置文件修改 (单位是 byte)

    在这里插入图片描述

  • 通过命令修改

在这里插入图片描述

查看redis内存使用情况

  • info memory
  • config get maxmemory

设置了maxmemory的选项,假如redis 内存使用达到上限,没有加上过期时间就会导致数据写满 maxmemory,这就需要内存淘汰策略

2.Redis 过期键的删除策略

  1. 立即删除

    • 对CPU不友好,用处理器性能换取存储空间(拿时间换空间)
  2. 惰性删除

    • 对memory 不友好,用存储空间换取处理器性能(拿空间换时间)

    • 开启惰性删除, lazyfree-lazy-eviction=yes

在这里插入图片描述

  1. 定期删除

    • 每隔一段时间执行一次删除过期键操作并通过限制删除操作执行时长和频率来减少删除操作对CPU时间的影响。
    • 定期抽样key,判断是否过期
    • 容易出现漏网之鱼

3.redis 缓存淘汰策略

在这里插入图片描述

3.1 LRU 和 LFU
  • LRU
    • 最近最少使用的页面置换算法,淘汰最长时间未被使用的页面,看页面最后一次被使用到发生调度的时间长短,首先淘汰最长时间未被使用的页面
  • LFU
  • 最近最不常用页面置换算法,淘汰一定时期内被访问次数最少的页面,看一定时间段内被访问次数最少的页,看一定时间段内页面被使用的频率,淘汰一定时期内被访问次数最少的页
3.2 8种缓存淘汰策略
  1. noevication : 不会驱逐任何key,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都返回 error
  2. allkeys-lru: 对所有key使用 LRU算法进行删除,优先删除掉最近不经常使用的key,用以保存新数据
  3. volatie-lru : 对所有设置了过期时间的key使用LRU 算法删除
  4. allkeys-random :对所有key随机删除
  5. volatie-random : 对所有设置了过期时间的key随机删除
  6. volatie-ttl :对所有设置了过期时间的key随即删除
  7. allkeys-lfu:对所有key使用LFU算法进行删除
  8. volatile-lfu:对所有设置了过期时间的key使用LFU算法进行删除

推荐使用

  • 在所有的 key 都是最近经常使用的,那么就需要选择 allkeys-lru 进行置换最近最不经常使用的key,如果不确定使用哪种策略,那么推荐使用 allkeys-lru
  • 如果所有的key的访问概率都是差不多的,那么可以选用 allkeys-random 策略去置换数据
  • 如果对数据有足够的了解,能够为key指定hint(expire/ttl指定),那么可以选择 volatile-ttl 进行置换(不大推荐,要求过高)

4.性能配置建议

  • 避免存储 bigkey
  • 开启惰性淘汰 lazyfree-lazy-eviction=yes

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

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

相关文章

线性代数:矩阵的秩

目录 一、矩阵的子式 二、矩阵的秩 三、重要性质定理推论 一、矩阵的子式 二、矩阵的秩 三、重要性质定理推论

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第十一章 反思C++面向对象与虚函数(下)

11.7.2 值语义与生命期 值语义的一个巨大好处是生命期管理很简单&#xff0c;就跟int一样——你不需要操心int的生命期。值语义的对象要么是stack object&#xff0c;要么直接作为其他object的成员&#xff0c;因此我们不用担心它的生命期&#xff08;一个函数使用自己stack上…

TryHackMe-File Inclusion练习

本文相关的TryHackMe实验房间链接&#xff1a;TryHackMe | Why Subscribe 路径遍历(目录遍历) LocationDescription/etc/issue包含要在登录提示之前打印的消息或系统标识。/etc/profile控制系统范围的默认变量&#xff0c;例如导出&#xff08;Export&#xff09;变量、文件创…

纯国产,3款黑科技软件,被误认为外国佬开发

闲话不多说&#xff0c;直接为大家推荐三款实用工具。 1、知犀思维导图 这款国产的思维导图工具&#xff0c;堪称业界的良心之选。它不仅能捕捉你每一个稍纵即逝的灵感&#xff0c;而且界面简洁、操作轻松。无论是团队协作、灵感记录、规划制定&#xff0c;还是日常笔记&…

jenkins添加linux节点

jenkins添加linux节点并创建任务_创建linux jenkins结点-CSDN博客文章浏览阅读1.1k次。jenkins添加linux节点并创建任务_创建linux jenkins结点https://blog.csdn.net/qq_32828053/article/details/128905581

加速知识检索:伯克利DeepMind联合研究,RaLMSpec让语言模型服务飞速提升2-7倍!

近年来&#xff0c;随着大型语言模型&#xff08;LLM&#xff09;的出现&#xff0c;在多样化的 NLP 任务上取得了令人瞩目的成果。然而&#xff0c;知识密集型任务仍是 NLP 领域中的一项挑战&#xff0c;因为这些任务不仅要求模型要理解和生成自然语言&#xff0c;还要能够访问…

【论文笔记】Multi-Chain Reasoning:对多思维链进行元推理

目录 写在前面1. 摘要2. 相关知识3. MCR方法3.1 生成推理链3.2 基于推理链的推理 4. 实验4.1 实验设置4.2 实验结果 5. 提及文献 写在前面 文章标题&#xff1a;Answering Questions by Meta-Reasoning over Multiple Chains of Thought论文链接&#xff1a;【1】代码链接&…

江科大stm32学习笔记11——旋转编码器计次

一、接线 旋转编码器&#xff0c;旋钮会不断接触断开触点产生电波。 由于两个电波之间相差90&#xff0c;即为正交波&#xff0c;一个电波处于高电平时另一个处于低电平&#xff0c;所以可以用来判断旋转方向。 二、代码 复制粘贴4-1的工程文件&#xff0c;重命名为“5-2 旋转…

Could not resolve host: github.com问题解决

git clone的时候发现机器无法解析github.com&#xff0c;其实应该改用ssh协议去clone&#xff0c;但是我用的是公用的机器&#xff0c;密钥对一直没配置好&#xff0c;所以也就堵死了。那么如果想让机器能解析github.com&#xff0c;&#xff08;机器本身没有ping命令&#xff…

深度学习入门笔记(五)前馈网络与反向传播

接着上一节,本节讲解模型自我学习的数学计算过程究竟是怎么样的。 5.1 前馈网络 一个最简单的前馈神经网络如图所示,对于每一个隐藏层,输入对应前一层每一个节点权重乘以节点输出值,输出则是经过激活函数(例如sigmoid函数)计算后的值。 在这样的网络中,输入的数据 x 经…

数据结构—基础知识(16):哈夫曼编码

数据结构—基础知识&#xff08;16&#xff09;&#xff1a;哈夫曼编码 哈夫曼编码的主要思想 在进行数据压缩时&#xff0c;为了使压缩后的数据文件尽可能短&#xff0c;可采用不定长编码。其基本思想是&#xff1a;为出现次数较多的字符编以较短的编码。为确保对数据文件进…

一、创建Vue3项目

1. 下载 node.js 下载地址&#xff1a;https://nodejs.org/zh-cn 优先选择 16 版本; node -v || node -version 可以检查本地 node.js 版本 2. 设置淘宝镜像源 npm config set registry https://registry.npmmirror.com/ 设置淘宝镜像源 npm config get registry 查看当前镜像…

【GitHub项目推荐--一款100% 开源的物联网开发平台,匹配智慧城市、智能家居和能源管理】【转载】

OpenRemote 一款100% 开源 - 集成您的设备、创建规则以及分析和可视化您的数据的物联网设备管理平台 github地址&#xff1a; https://github.com/openremote/openremote 国内源代码&#xff1a; http://www.gitpp.com/pythonking/openremote OpenRemote 的介绍 OpenRemo…

格式化内存卡后,如何找回丢失的监控视频?

随着摄像头的应用越来越广泛&#xff0c;很多监控摄像头采用了内存卡作为存储介质&#xff0c;方便用户存储和查看摄像头拍摄的视频文件。然而&#xff0c;由于各种原因&#xff0c;监控摄像头的内存卡有时会被意外格式化导致重要数据的丢失&#xff0c;给用户带来诸多困扰。 那…

因子图、边缘化与消元算法的抽丝剥茧 —— Notes for “Factor Graphs for Robot Perception“

Title: 因子图、边缘化与消元算法的抽丝剥茧 —— Notes for “Factor Graphs for Robot Perception” 文章目录 I. 前言II. 因子图的基本概念1. 因子图的定义2. SLAM 中的因子图A. 因子图的图示B. 因子图的因式C. 因子图的二分图形式 III. 边缘化与消元运算的基本原理1. 边缘化…

19. 删除链表的倒数第 N 个结点(力扣LeetCode)

文章目录 19. 删除链表的倒数第 N 个结点题目描述将删除倒数第n个节点转化为删除第n个节点双指针 19. 删除链表的倒数第 N 个结点 题目描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;hea…

LeetCode_17_中等_电话号码的字母组合

文章目录 1. 题目2. 思路及代码实现&#xff08;Python&#xff09;2.1 回溯 1. 题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应…

中国(合一)民营企业家高峰论坛暨2024精英校友会10周年庆在上饶举行!

1月29日下午&#xff0c;“中国&#xff08;合一&#xff09;民营企业家高峰论坛暨2024精英校友会10周年庆典”在上饶市饶商金茂诚悦酒店举行。出席会议的嘉宾有民建上饶市委会专职副主委方乾文、民建上饶市委会秘书长尹林、上饶市民营&#xff08;个私)经济协会会长傅利平、上…

大数据时代效率革新:数字化管理助力企业迈向全新高度-亿发

在大数据时代的浪潮中&#xff0c;数字化管理成为企业不可或缺的发展趋势。以信息技术为支撑&#xff0c;数字化管理为企业带来了前所未有的机遇和挑战。让我们一起探讨&#xff0c;在这个数字时代&#xff0c;数字化管理如何引领企业走向更加高效、智能的未来。 1. 数据驱动决…

【JAVA】ReentrantLock 显式锁定的类

ReentrantLock 是 Java 中用于进行显式锁定的类&#xff0c;它提供了与 synchronized 关键字类似的互斥性和可重入性&#xff0c;但相比于 synchronized&#xff0c;它提供了更灵活的锁定方式。下面对 ReentrantLock 进行详解&#xff1a; 一、ReentrantLock 是什么&#xff1…