Bitmap,布隆过滤器初步了解

news2024/11/16 1:56:52

布隆过滤器使用教程

文章目录

  • 布隆过滤器使用教程
    • 1.背景
    • 2.什么是Bitmap
    • 3.布隆过滤器
      • 3.1 什么是布隆过滤器
      • 3.2 布隆过滤器的作用
      • 3.3 布隆过滤器的基本原理
    • 4.布隆过滤器的实现Guava和Redisson
      • 4.1 实现思路
      • 4.2 SpringBoot实现这些操作Bitmap,guava,redisson布隆过滤器

1.背景

最近公司对所有请求响应的数据进行推送kafka到大数据,然后落入数仓进行数据分析, 但是要解决请求重复推送的问题,可以容忍重复存在但是不能太多,所以就想到了bitmap和已经成型的布隆过滤器

2.什么是Bitmap

操作String数据结构的key所存储的字符串指定偏移量上的,返回原位置的值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YXQ8sGx6-1670483948742)(D:\学习乐园\文档总结\杂记\picture\bitmap.png)]
优点

  • 节省空间:通过一个bit位来表示某个元素对应的值或者状态,其中key就是对应元素的值。实际上8个bit可以组成一个Byte,所以是及其节省空间的。
  • 效率高:setbitgetbit的时间复杂度都是O(1),其他位运算效率也高。

缺点

  • 本质上只有01的区别,所以用做业务数据记录,就不需要在意value的值。

使用场景

  1. 可作为简单的布尔过滤器来判断用户是否执行过某些操作;

  2. 可以计算用户日活、月活、留存率的统计;

  3. 可以统计用户在线状态和人数;

3.布隆过滤器

3.1 什么是布隆过滤器

介绍布隆过滤器之前,先介绍一下哈希函数,我们在Java中的HashMap,HashSet也接触过hashcode()这个函数。

哈希函数指将哈希表中元素的关键键值通过一定的函数关系映射为元素存储位置的函数。

哈希函数的特点

  • 如果根据同一个哈希函数得到的哈希值不同,那么这两个哈希值的原始输入值肯定不同
  • 如果根据同一个哈希函数得到的两个哈希值相等,两个哈希值的原始输入值有可能相等,有可能不相等

布隆过滤器实际上是一个非常长的二进制向量(bitmap)和一系列随机哈希函数。

布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。 Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。

它是一个判断元素是否存在集合的快速的概率算法。Bloom Filter有可能会出现错误判断,但不会漏掉判断。也就是Bloom Filter判断元素不再集合,那肯定不在。如果判断元素存在集合中,有一定的概率判断错误。因此,Bloom Filter”不适合那些“零错误的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter比其他常见的算法(如hash,折半查找)极大节省了空间。

优点

  • 布隆过滤器存储空间和插入/查询时间都是常数
  • Hash函数相互之间没有关系,方便由硬件并行实现
  • 布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势
  • 布隆过滤器可以表示全集,其它任何数据结构都不能

缺点

  • 有一定的误判率

    常见的补救办法是建立一个小的白名单,存储那些可能被误判的元素。但是如果元素数量太少,使用散列表足矣。

  • 一般情况下不能从布隆过滤器中删除元素。

    我们很容易想到把位列阵变成整数数组,每插入一个元素相应的计数器加1, 这样删除元素时将计数器减掉就可以了。然而要保证安全的删除元素并非如此简单。首先我们必须保证删除的元素的确在布隆过滤器里面,这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。

3.2 布隆过滤器的作用

  • 解决Redis缓存穿透
  • 邮件过滤,使用布隆过滤器来做邮件黑名单过滤
  • 解决视频推荐过的不再推荐

3.3 布隆过滤器的基本原理

  • 布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。
  • 检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。
  • Bloom Filter跟单哈希函数Bit-Map不同之处在于:Bloom Filter使用了k个哈希函数,每个字符串跟k个bit对应。从而降低了冲突的概率。
    在这里插入图片描述
    步骤
  1. 首先,建立一个二进制向量,并将所有位设置为0。
  2. 然后,选定K个散列函数,用于对元素进行K次散列,计算向量的位下标。
  3. 添加元素:当添加一个元素到集合中时,通过K个散列函数分别作用于元素,生成K个值作为下标,并将向量的相应位设置为1。
  4. 检查元素:如果要检查一个元素是否存在集合中,用同样的散列方法,生成K个下标,并检查向量的相应位是否全部是1。如果全为1,则该元素很可能在集合中;否则(只要有1个或以上的位为0),该元素肯定不在集合中。

4.布隆过滤器的实现Guava和Redisson

4.1 实现思路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KzrbZgG3-1670483948745)(D:\学习乐园\文档总结\杂记\picture\布隆过滤器设计流程.png)]

4.2 SpringBoot实现这些操作Bitmap,guava,redisson布隆过滤器

引入依赖

<?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.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>RedisBitMapProject</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>RedisBitMapProject</name>
    <description>RedisBitMapProject</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

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

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

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

        <!--pool2,redis连接池使用-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <!--guava 布隆过滤器-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.20</version>
        </dependency>

        <!--redisson 布隆过滤器-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.18.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

yml配置

server:
  port: 20010

#redis????
spring:
  redis:
    host: localhost             #redis??
    port: 6379                  #redis??
    database: 0                 #redis??(0-15,???0)
    timeout: 1000               #redis??????
    lettuce:                    #??lettuce???
      pool:
        max-active: 20          #????????(??????????)
        max-wait: -1            #???????????(??????????)
        min-idle: 0             #???????????
        max-idle: 10            #???????????

guava布隆过滤器配置类

package com.example.bitmap.config;

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.nio.charset.Charset;

/**
 * @Author Emperor Kang
 * @ClassName BloomFilterConfig
 * @Description guava布隆过滤器配置类
 * @Date 2022/12/7 15:37
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@Configuration
public class GuavaBloomFilterConfig {

    @Bean
    public BloomFilter<String> guavaBloomFilter(){
        //expectedInsertions:容量期望大小
        //fpp:期望的误判率,期望的误判率越低,布隆过滤器计算时间越长
        BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("UTF-8")), 1000, 0.000001);
        return bloomFilter;
    }

}

redisson布隆过滤器配置类

package com.example.bitmap.config;

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author Emperor Kang
 * @ClassName RedissonBloomFilterConfig
 * @Description RedissonBloomFilterConfig
 * @Date 2022/12/7 17:39
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@Configuration
public class RedissonBloomFilterConfig {
    @Autowired
    private RedissonClient redissonClient;

    @Bean
    public RBloomFilter<String> redissonBloomFilter(){
        RBloomFilter<String> redissonBloomFilter = redissonClient.getBloomFilter("redissonBloomFilter");
        //初始化布隆过滤器:预计元素为1000L,误差率为0.00001
        redissonBloomFilter.tryInit(1000L,0.00001);
        return redissonBloomFilter;
    }
}

redisson配置

package com.example.bitmap.config;

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @Author Emperor Kang
 * @ClassName RedissonConfig
 * @Description redisson配置类
 * @Date 2022/12/7 17:19
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@Component
@Configuration
@Slf4j
public class RedissonConfig {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private String port;

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://"+host+":"+port);
        return Redisson.create(config);
    }
}

redis配置类

package com.example.bitmap.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;

@Configuration
public class RedisConfig {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 实例化RedisAtomicLong
     * @return
     */
    @Bean
    public RedisAtomicLong redisAtomicLong() {
        RedisAtomicLong redisAtomicLong = new RedisAtomicLong("bitMapIncreaseKey", redisTemplate.getConnectionFactory());
        return redisAtomicLong;
    }

}

utils

package com.example.bitmap.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

/**
 * @Author Emperor Kang
 * @ClassName RedisUtil
 * @Description redis工具类
 * @Date 2022/12/7 10:19
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@Component
@Slf4j
public class RedisUtil {
    @Autowired
    private RedisAtomicLong redisAtomicLong;

    /**
     * 生成自增的偏移量序号
     * @return
     */
    public Long bitMapOffsetSequence(){
        long sequence = 0L;
        try {
            if(redisAtomicLong.get() == 0){
                redisAtomicLong.getAndSet(0L);
            }
            sequence = redisAtomicLong.incrementAndGet();
            log.info("当前序号为:{}",sequence);
        } catch (Exception e) {
            log.error("RedisUtil.bitMapOffsetSequence生成自增偏移量时发生异常",e);
            throw e;
        }
        return sequence;
    }

}

controller

package com.example.bitmap.controller;

import com.alibaba.fastjson.JSON;
import com.example.bitmap.vo.BloomFilterRequestVo;
import com.google.common.hash.Funnels;
import com.google.common.hash.Hashing;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.Charset;

/**
 * @Author Emperor Kang
 * @ClassName BitMapController
 * @Description TODO
 * @Date 2022/12/8 10:36
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@RestController
@RequestMapping("/bitmap")
@Slf4j
public class BitMapController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * bitmap去重操作
     * @param requestVo
     * @return
     */
    @RequestMapping("/distinct")
    public Object distinctData(@RequestBody BloomFilterRequestVo requestVo){
        log.info("bitmap-requestVo:{}", JSON.toJSONString(requestVo));
        String key = buildKey(requestVo);
        long offset = hash(key);
        log.info("当前的offset:{}",offset);
        //判断是否可能存在该key
        if(redisTemplate.opsForValue().getBit(key,offset)){
            log.info("该key:{}可能已经存在,所以不再推送kafka",key);
        }else{
            log.info("该key:{}不存在,开始推送kafka,将该key写入布隆过滤器",key);
            redisTemplate.opsForValue().setBit(key,offset,true);
        }
        return true;
    }

    private String buildKey(BloomFilterRequestVo requestVo) {
        return requestVo.getApplySeq() + "_" + requestVo.getInterfaceCode();
    }


    /**
     * guava依赖获取hash值。
     */
    private long hash(String key) {
        Charset charset = Charset.forName("UTF-8");
        return Math.abs(Hashing.murmur3_128().hashObject(key, Funnels.stringFunnel(charset)).asInt());
    }

}

package com.example.bitmap.controller;

import com.alibaba.fastjson.JSON;
import com.example.bitmap.vo.BloomFilterRequestVo;
import com.google.common.hash.BloomFilter;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author Emperor Kang
 * @ClassName BloomFilterController
 * @Description 布隆过滤器
 * @Date 2022/12/7 15:44
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@RestController
@RequestMapping("bloomFilter")
@Slf4j
public class BloomFilterController {

    @Autowired
    @Qualifier("guavaBloomFilter")
    private BloomFilter<String> guavaBloomFilter;

    @Autowired
    @Qualifier("redissonBloomFilter")
    private RBloomFilter<String> redissonBloomFilter;

    /**
     * guava布隆过滤器
     * @param requestVo
     * @return
     */
    @PostMapping("/guava")
    public Object guavaBloomFilter(@RequestBody BloomFilterRequestVo requestVo){
        log.info("guava-requestVo:{}", JSON.toJSONString(requestVo));
        String key = buildKey(requestVo);
        //判断是否可能存在该key
        if(guavaBloomFilter.mightContain(key)){
            log.info("该key:{}可能已经存在,所以不再推送kafka",key);
        }else{
            log.info("该key:{}不存在,开始推送kafka,将该key写入布隆过滤器",key);
            guavaBloomFilter.put(key);
        }
        return true;
    }

    /**
     * guava布隆过滤器
     * @param requestVo
     * @return
     */
    @PostMapping("/redisson")
    public Object redissonBloomFilter(@RequestBody BloomFilterRequestVo requestVo){
        log.info("redisson-requestVo:{}", JSON.toJSONString(requestVo));
        String key = buildKey(requestVo);
        //判断是否可能存在该key
        if(redissonBloomFilter.contains(key)){
            log.info("该key:{}可能已经存在,所以不再推送kafka",key);
        }else{
            log.info("该key:{}不存在,开始推送kafka,将该key写入布隆过滤器",key);
            redissonBloomFilter.add(key);
        }
        return true;
    }

    private String buildKey(BloomFilterRequestVo requestVo) {
        return requestVo.getApplySeq() + "_" + requestVo.getInterfaceCode();
    }
}

package com.example.bitmap.controller;

import com.example.bitmap.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author Emperor Kang
 * @ClassName RedisController
 * @Description TODO
 * @Date 2022/12/7 10:21
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@RestController
@RequestMapping("/redis")
@Slf4j
public class RedisController {
    public static final List<Long> list = Collections.synchronizedList(new ArrayList<>());

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 自增主键ID
     * @return
     */
    @RequestMapping("incrId")
    public Object generateIncrId(){
        Long offsetSequence = redisUtil.bitMapOffsetSequence();
        list.add(offsetSequence);
        return true;
    }

    /**
     * 查看生成的主键ID是否有重复
     */
    @RequestMapping("/distinct")
    public void getDis(){
        log.info("当前集合size:{}",list.size());
        List<Long> collect = list.stream()
                .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
                .entrySet()
                .stream()
                .filter(e -> e.getValue() > 1)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        log.info("重复的数据为{}",collect);
    }
}

jmeter进行调起测试
在这里插入图片描述
结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJi8JObQ-1670483948746)(D:\学习乐园\文档总结\杂记\picture\image-20221208151649700.png)]

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

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

相关文章

redis知识点汇总

一、Redis的数据类型和数据结构 1、Redis五种数据类型 String&#xff08;字符串&#xff09;、List&#xff08;列表&#xff09;、Hash&#xff08;哈希&#xff09;、Set&#xff08;集合&#xff09;和Sorted Set&#xff08;有序集合&#xff09;。 2、Redis的底层数据…

C# 数据类型分值类型及引用类型

一 程序中的变量与常量 程序的基本任务是&#xff1a;对数据进行处理&#xff1b; 数据分为变量(variable)与常量(literal) int age18; 变量是值可以改变&#xff0c;本质上是内存的空间&#xff0c;用来存储信息 常量的值是固定的&#xff0c;直接写出来的&#xff0c;称字面…

点击按钮,下载文件

实现文件的下载功能 1、使用a标签 直接下载仅适用于浏览器无法识别的文件。 如果是浏览器支持的文件格式&#xff0c;如html、jpg、png、pdf等&#xff0c;则不会触发文件下载&#xff0c;而是直接被浏览器解析并展示 <ahref"http://xxxxxx.rar"download>下载…

vue中的性能优化

文章目录一、Vue为什么要做性能优化二、如何做vue的性能优化1. 网络请求优化link标签项目静态资源压缩懒加载利用浏览器的缓存机制高效复用项目文件总结2. 代码优化3. 用户体验优化场景1场景2一、Vue为什么要做性能优化 性能优化的目的是使网站的加载速度更快&#xff0c;用户…

【语音处理】基于自适应差分脉冲编码调制(ADPCM)的实现研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步进步&#xff0c;matlab项目目标合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信息&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算…

音视频直播系统之 WebRTC 中的协议UDP、TCP、RTP、RTCP详解

一、UDP/TCP 如果让你自己开发一套实时互动直播系统&#xff0c;在选择网络传输协议时&#xff0c;你会选择使用UDP协议还是TCP协议 假如使用 TCP 会怎样呢&#xff1f;在极端网络情况下&#xff0c;TCP 为了传输的可靠性&#xff0c;将会进行反复重发信息的操作 在 TCP 协议…

Nagios篇之Nagios服务关联飞书实现消息告警

一、前言 通常情况下&#xff0c;我们在利用Nagios监控来做服务器监控时&#xff0c;告警是必不可少的&#xff0c;以便于运维人员能够及时发现异常&#xff0c;进而处理问题&#xff0c;所以关联Nagios就变得极为重要。 Nagios关联告警的形式很多&#xff0c;可以进行短信推送…

wpf-ListView中放置可动态调节范围的刻度尺

需求描述 某个ListView占据整个窗口&#xff0c;当窗口的宽度发生改变时&#xff0c;某一列中显示的、某一行的字符数目&#xff0c;能跟随窗口宽度变化而增减。 下面是我做完的效果&#xff1a;&#xff08;只展示窗口的一部分&#xff09; 此时是窗口缩放的极限&#xff0…

为什么全光谱台灯对孩子眼睛好呢?台灯全光谱到底是什么意思

相信大家在购买台灯时有经常看到“全光谱”、“高显色”等关键词&#xff0c;其实这指的是台灯的某方面特性&#xff0c;所谓全光谱&#xff0c;就是指光线的光谱成分完全&#xff0c;与自然光别无二致。 我们都知道&#xff0c;一束自然太阳光不是由某个单一成分构成&#xff…

Briefings in Bioinformatics2021 | 药物挖掘分子设计--生成模型综述

原文标题&#xff1a;Molecular design in drug discovery: a comprehensive review of deep generative models 论文地址&#xff1a;Molecular design in drug discovery: a comprehensive review of deep generative models | Briefings in Bioinformatics | Oxford Academ…

35_DMA基本原理

目录 DMA简介 DMA框图 STM32的DMA有一下一些特征 DMA1控制器 DMA处理 数据方向 仲裁器 DMA通道 可编程的数据量 指针增量 循环模式 存储器到存储器模式 通道传输数据量 中断 通道配置过程 DMA简介 DMA全称Direct Memroy Access, 既直接存储器访问。 DMA传输将…

重编内核导致ubuntu有线连接不出现的问题

网卡是intel的i225v 千兆网卡&#xff0c;系统为ubuntu18.0.4&#xff0c;原始内核为5.4.0-135-generic&#xff0c;但是重新编译出错&#xff0c;不知道少了什么东西&#xff0c;也没去深究&#xff0c;重新下载了5.9.0的内核&#xff1b;结果重新编译内核重启有线网卡就不能用…

2.MyBatis环境搭建

数据准备 CREATE TABLE user (id int(11) NOT NULL,username varchar(30) NOT NULL,sex varchar(1) NOT NULL,birthday varchar(10) NOT NULL,address varchar(100) NOT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8;insert into user values(1,"steven&qu…

ADI Blackfin DSP处理器-BF533的开发详解2:开发环境的搭建

软硬件开发环境的搭建 纯流程化的东西&#xff0c;没什么技术含量&#xff0c;照着做就行了。 开发板和仿真器进行物理链接&#xff0c;也就是插上JTAG头。 特别特别特别注意&#xff0c;仿真器和开发板均不上电的情况下插JTAG头&#xff0c;不要带电插JTAG头&#xff0c;你…

ORB-SLAM2 ---- Frame::GetFeaturesInArea函数

目录 1.函数用处 2.步骤 3.code 4.函数解释 4.1 函数思想 4.2 代码解释 1.函数用处 找到在 以为中心&#xff0c;半径为的圆形内且金字塔层级在的特征点。 2.步骤 Step 1 计算半径为r圆左右上下边界所在的网格列和行的id Step 2 遍历圆形区域内的所有网格&#xff0c…

代码随想录Day44|完全背包、518.零钱兑换II、377.组合总和IV

文章目录完全背包518.零钱兑换II377.组合总和IV完全背包 文章链接:代码随想录 (programmercarl.com) 背包最大重量为4。 物品为&#xff1a;如果求组合数就是外层for循环遍历物品&#xff0c;内层for遍历背包。 如果求排列数就是外层for遍历背包&#xff0c;内层for循环遍历…

Linux多线程C++版(九) 线程同步和互斥-----线程信号量

目录1.基本概念2.信号量创建和销毁3.信号量加和减操作4.代码理解信号量5.信号量实例银行账户取款----实现互斥6.信号量实例计算和取结果----实现线程同步1.基本概念 信号量从本质上是一个非负整数计数器&#xff0c;是共享资源的的数目&#xff0c;通常被用来控制对共享资源的…

[附源码]JAVA毕业设计同学录网站(系统+LW)

[附源码]JAVA毕业设计同学录网站&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#…

从源码出发剖解正则表达式

✨✨hello&#xff0c;愿意点进来的小伙伴们&#xff0c;你们好呐&#xff01; &#x1f43b;&#x1f43b;系列专栏&#xff1a;【JavaSE】 &#x1f432;&#x1f432;本篇内容&#xff1a;详解正则表达式 &#x1f42f;&#x1f42f;作者简介:一名现大二的三非编程小白&…

[ MySQL ] 使用Navicat进行MySQL数据库备份 / 还原(备份.nb3文件方式)

本文主要讲解如何用Navicat&#xff08;Navicat Premium &#xff0c;或者Navicat for mysql&#xff09;进行MySQL备份和恢复数据库。 本文主要大纲为&#xff1a;使用Navicat备份工具方式进行备份和还原&#xff0c;其中包括还原自身数据库和还原到其他目标库。 文章目录一、…