Elasticsearch 处理地理信息

1、GeoHash

​ GeoHash是一种地理坐标编码系统,可以将地理位置按照一定的规则转换为字符串,以方便对地理位置信息建立空间索引。首先要明确的是,GeoHash代表的不是一个点而是一个区域。GeoHash具有两个显著的特点:一是通过改变 GeoHash的长度,我们可以表示任意精度的位置:GeoHash越短,其表示的区域越大,位置精度越低;相反,GeoHash越长,其表示的区域越小,位置精度越高。Elasticsearch 支持GeoHash字符串长度是12,这个精度已经达到了厘米级别;二是如果不同位置的GeoHash字符串前缀相同,那他们一定在同一个区域中。

​ GeoHash将地理坐标编码为字符串的方法与二分查找有几分相识。它将经纬度范围一分为二,分成左右两个区间;坐标落入左区间为0,落入右区间为1。按照此方法,分别对精度和维度不停地地柜逼近实际坐标值,就会得到两组由0,1组成的数字字符串。然后按照偶数位放经度,奇数位放纬度的方法,将两组数据串联组合起来。最后将组合的数字串转换成十进制,并用Base32对数字进行编码就得到GeoHash最终编码了。

​ 根据经纬度的定义,经度整体范围为: [ -180 , 180 ] ,纬度整体范围为:[ -90 , 90 ]。所以第一次递归分割坐标后,经度的左右区间为 **[ -180 , 0 ) **和

[ 0 , 180 ],即西半球和东半球 纬度的左右区间为 **[ -90 , 0 ) [ 0 , 90 ],即南半球和北半球。以山东济南某地坐标( 117.15838 , 36.74038 )**为例,经纬度第一次递归后都落入到右区间,则他们第一位数字都是1。由于落入了右区间,所以经纬第二次递归就是针对右区间分割:经度为 **[ 0 , 90 ) **和 [ 90 , 180 ],纬度为

[ 0 , 45 ) [ 45 , 90 ] 。这次经度落入到了右区间,二纬度落入了左区间,所以他们的第二位数字分别为10。按照此方法不停的递归下去,就能无线的接近于实际坐标。

​ 可以看出,GeoHash时间上是将地球假设为一个平面,然后在这个平面上划分网格的过程。在这个递归的过程中,每一次都是将整个区域一分为二,区域面积也就约分越小,而且在相同区域的位置他们的前缀数字一定是相同的。表1-1列出了经度 117.15838经过十次递归运算过程及结果。

表1-1 GeoHash经度 117.15838

次数经度范围左区间 - 0右区间 - 1117.15838
1[ -180 , 180 ][ -180 , 0 )[ 0 , 180 ]1
2[ 0 , 180 ][ 0 , 90 )[ 90 , 180 ]1
3[ 90 , 180 ][90 , 135 )[ 135 , 180 ]0
4[ 90 , 135 )[ 90, 112.5 )[ 112.5 , 135 )1
5[ 112.5 , 135 )[ 112.5 , 123.75 )[ 123.75 , 135 )0
6[ 112.5 , 123.75 )[ 112.5 , 118.125 )[ 118.125 , 123.75)0
7[ 112.5 , 118.125 )[ 112.5 , 115.3125 )[ 115.3125 , 118.125)1
8[ 115.3125 , 118.125)[ 115.3125 , 116.71875 )[ 116.71875 , 118.125 )1
9[ 116.71875 , 118.125 )[ 116.71875 , 117.421875 )[ 117.421875 , 118.125 )0
10[ 116.71875 , 117.421875 )[ 116.71875 ,117.0703125 )[ 117.0703125, 117.421875 )1

​ 经过10次递归,经度为117.15838得到的数字字符串为1101001101,以同样的方式对纬度做GeoHash运算,表1-2列出了纬度 36.74038经过十次递归运算过程及结果。

表1-2 GeoHash纬度 36.74038

次数经度范围左区间 - 0右区间 - 136.74038
1[ -90, 90][ -90 , 0 )[ 0 , 90]1
2[ 0 , 90][ 0 , 45)[ 45, 90]0
3[ 0 , 45)[0, 22.5)[ 22.5, 45 )1
4[ 22.5, 45)[ 22.5, 33.75 )[ 33.75 , 45)1
5[ 33.75 , 45)[ 33.75, 39.375 )[ 39.375 , 45 )0
6[ 33.75, 39.375 )[ 33.75, 36.5625 )[ 36.5625 , 39.375)1
7[ 36.5625 , 39.375)[ 36.5625 , 37.96875)[ 37.96875 , 39.375)0
8[ 36.5625 , 37.96875)[ 36.5625 , 37.265625 )[ 37.265625 , 37.96875 )0
9[ 36.5625 , 37.265625 )[ 36.5625, 36.9140625 )[ 36.9140625 , 37.265625 )0
10[ 36.5625, 36.9140625 )[ 36.5625 ,36.7385625 )[ 36.7385625 , 36.9140625 )1

同样经过十次递归,纬度得到的数字串为1011010001 ,下面按偶数位经度,奇数位纬度的方法合并两个数字串,注意位数是从0开始,或者理解为先经度后纬度,各区一位交叉合并。

经度:1101001101

纬度:1011010001

合并:11100 11100 01101 00011

合并后结果按照每五位一组,一次转换成十进制数 28、28、13、3,并使用表1-3对应的Base32编码转为字符串。

表 1- 3
在这里插入图片描述

​ 最终结果为wwe34,可以到 http://geohash.org/ 网站上输入"36.74038,117.15838" 验证结果为:wwe3402hhp5z 这个结果为12位,说明做了30次递归。

表1-4列出了GeoHash字符串长度与实际位置误差关系。

表 1- 4 GeoHash字符串长度与实际位置关系

GeoHash长度纬度位数经度位数纬度误差经度误差区域面积
123±23±235009.4km*4992.6km
255±2.8±5.61252.3km*624.1km
378±0.70±0.70156.5km*156km
41010±0.087±0.1839.1km*19.5km
51213±0.022±0.0224.9km*4.9km
61515±0.0027±0.00551.2km*609.4m
71718±0.00068±0.00068152.9m*152.4m
82020±0.000085±0.0001738.2m*19m
92223±0.000021±0.0000214.8m*4.8m
102525±0.00000268±0.000005361.2m*59.5cm
112728±0.00000067±0.000000674.9cm*14.9cm
123030±0.00000008±0.000000173.7cm*1.9cm

​ 根据图1-4表示,当GeoHash字符串长度达到12位时,位置经度误差可以控制在不到8cm²的范围内。

2、地理类型字段

​ Elasticsearch 提供了两种地理相关的数据类型geo_pointgeo_shape,前者用于保存地理位置,即具体的某一个坐标;而后者用于保存地理形状,如矩形和多边形。

1. geo_point 类型

​ 地理位置由经度和维度共同定义,所以geo_point定义地理位置坐标最基本的形式也是通过提供经度和纬度来实现的。

如下:存储了数据的日期、主键、地理位置信息

PUT /obd
{
	"mapping":{
        "properties":{
            "datadate": {  //数据日期
            	"type": "date"
            },
            "id": {   //数据主键
            	"type": "long"
            },
            "location": {  //地理位置信息
            	"type": "geo_point"
            },
            "name": {  //名称(编号)
           		 "type": "text"
            }
        }
	}
}

​ 如上,location的数据类型为geo_point,这种类型有四种表示形式

​ 例如:

# 格式1 对象
PUT /obd/_doc/1
{
  "location": { 
    "lat": 41.12,
    "lon": -71.34
  }
}
# 格式2 数组
PUT /obd/_doc/2
{
  "location": [ -71.34, 41.12 ] 
}
# 格式3 字符串
PUT /obd/_doc/3
{
  "location": "41.12,-71.34" 
}
# 格式4 geohash
PUT /obd/_doc/4
{
  "location": "wwe3402hhp5z" 
}

2、基于geo_point类型的查询(java)

  • 按距离搜索

  • 按距离排序

  • 按时间范围

maven依赖

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
<dependencies>
        <!--必备: spring boot web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--es-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!-- druid 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>2.5.4</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>
    </dependencies

配置文件yml

spring:
  elasticsearch:
    rest:
      uris: 192.168.254.190:9200,192.168.254.191:9200,192.168.254.192:9200
  datasource:
    druid:
      stat-view-servlet:
        # 默认true 内置监控页面首页/druid/index.html
        enabled: false
      initial-size: 20
      max-active: 60
      min-idle: 20
      max-wait: 30000
    dynamic:
      primary: master
      strict: false
      datasource:
        master: ***
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: ***
          url: 
        jdc:
          url: ***
          driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
          username: sa
          password: ***

数据库实体

@Data
@EqualsAndHashCode()
@TableName("carPosition")
public class CarPosition {

    @TableId(value = "id")
    private Long id;

    @TableField("vehicleIdentificationNumber")

    private String vehicleIdentificationNumber;
    @TableField("collectionTime")
    private LocalDateTime collectionTime;
    /**
     * 经度
     */
    private String longitude;
    /**
     * 纬度
     */
    private String latitude;



}

es实体

@Data
@FieldNameConstants
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "#{@dynamicIndex.getIndex()}", createIndex = false)
public class ObdModel implements Serializable {

    @Id
    private Long id;

    @Field(type = FieldType.Text)
    private String name;

    @GeoPointField
    private GeoPoint location;

    @Field(type = FieldType.Date, format = DateFormat.custom, pattern ="yyyy-MM-dd HH:mm:ss:SSS")
    private LocalDateTime datadate;
}

将数据库数据存储到es


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.sunfeng.elasticsearch.entity.CarPosition;
import com.sunfeng.elasticsearch.es.model.ObdModel;
import com.sunfeng.elasticsearch.es.repository.ObdModelRepository;
import com.sunfeng.elasticsearch.es.utils.DynamicIndex;
import com.sunfeng.elasticsearch.service.CarPositionService;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.common.geo.GeoPoint;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;


import javax.annotation.Resource;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.sunfeng.elasticsearch.es.utils.DateTimeFormatterUtil.yyyy_MM_dd_HH_mm_ss;


@Slf4j
@SpringBootTest
class ElasticsearchSpringdataApplicationTests {

    @Resource
    private ObdModelRepository obdModelRepository;

    @Resource
    private DynamicIndex dynamicIndex;

    @Resource
    private ElasticsearchRestTemplate restTemplate;

    @Resource
    private CarPositionService carPositionService;
		
    @Test
    public void createIndex() {
        //生成索引名称
        String obdIndex = "obd2";
        Document mapping = restTemplate.indexOps(IndexCoordinates.of(obdIndex)).createMapping(ObdModel.class);
        //判断索引库中是否存在该索引
        if (!restTemplate.indexOps(IndexCoordinates.of(obdIndex)).exists()) {
            restTemplate.indexOps(IndexCoordinates.of(obdIndex)).create();
            //创建映射
            restTemplate.indexOps(IndexCoordinates.of(obdIndex)).putMapping(mapping);
        }
    }


    @Test
    public void contextLoads() {
        dynamicIndex.setIndex("obd");
        Iterable<ObdModel> all = obdModelRepository.findAll();

        all.forEach(System.out::println);
        dynamicIndex.setIndex("");
    }
	//纬度正则
    private static String latReg = "^[\\-\\+]?((0|([1-8]\\d?))(\\.\\d{1,6})?|90(\\.0{1,6})?)$";
	//经度正则
    private static String lonReg = "^[\\-\\+]?(0(\\.\\d{1,6})?|([1-9](\\d)?)(\\.\\d{1,6})?|1[0-7]\\d{1}(\\.\\d{1,6})?|180(\\.0{1,6})?)$";

    public static void main(String[] args) {
        System.out.println(LocalDateTime.parse("2023-08-04 19:00:00", yyyy_MM_dd_HH_mm_ss).toInstant(ZoneOffset.of("+8")).toEpochMilli());
    }
 @Test
    public void dbToEs() {

        log.info("开始统计!!");

        LambdaQueryWrapper<CarPosition> lambdaQueryWrapper = new LambdaQueryWrapper<CarPosition>();


        dynamicIndex.setIndex("obd202308");


        List<CarPosition> carPositionList = carPositionService.list(lambdaQueryWrapper);
        /**
         * 获取分页数据
         */
        log.info("需要处理的数据量为:{}", carPositionList.size());

        carPositionList = carPositionList.parallelStream()
                .filter(carPosition -> ObjectUtil.isNotEmpty(carPosition.getLatitude()) &&
                        ObjectUtil.isNotEmpty(carPosition.getLongitude()) &&
                        ReUtil.isMatch(latReg, carPosition.getLatitude()) &&
                        ReUtil.isMatch(lonReg, carPosition.getLongitude())).collect(Collectors.toList());
        log.info("排除部分脏数据后为:{}", carPositionList.size());
        ArrayList<ObdModel> obdModels = new ArrayList<>();
        //批量保存提高效率
        for (int i = 0; i < carPositionList.size(); i++) {
            CarPosition carPosition = carPositionList.get(i);

            ObdModel obdModel = new ObdModel();
            obdModel.setId(carPosition.getId());
            obdModel.setName(carPosition.getVehicleIdentificationNumber());
            obdModel.setDatadate(carPosition.getCollectionTime());
            GeoPoint geoPoint = new GeoPoint(Double.parseDouble(carPosition.getLatitude()), Double.parseDouble(carPosition.getLongitude()));
            obdModel.setLocation(geoPoint);
            obdModels.add(obdModel);
            if (obdModels.size() % 10000 == 0) {
                log.info("开始保存");
                obdModelRepository.saveAll(obdModels);
                log.info("结束保存");
                obdModels.clear();
            }
        }
        obdModelRepository.saveAll(obdModels);
    }

}

es数据查询

package com.sunfeng.elasticsearch;


import com.sunfeng.elasticsearch.es.utils.DateTimeFormatterUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;

import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Map;


import static com.sunfeng.elasticsearch.es.utils.DateTimeFormatterUtil.getDateTimeOfTimestamp;
import static com.sunfeng.elasticsearch.es.utils.DateTimeFormatterUtil.yyyy_MM_dd_HH_mm_ss;

@Slf4j
@SpringBootTest
public class TestSearchDocument {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @Test
    public void contextLoads() throws IOException {

        //创建查询请求
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("obd202308");

        GeoPoint geoPoint = new GeoPoint(36.508270D, 117.848530D);
        //条件1、设置搜索半径
        GeoDistanceQueryBuilder distanceQueryBuilder = QueryBuilders.geoDistanceQuery("location")
                .point(geoPoint)
                .distance(10000, DistanceUnit.METERS)
                .geoDistance(GeoDistance.ARC); //设置查询精度
        
       
        
        //条件3、设置搜索区间 时间区间
        //注意: 时间格式要用 yyyy-MM-dd HH:mm:ss:SSS
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("datadate")
                .gt("2023-08-04 19:00:00:000")
                .lte("2023-08-04 20:00:00:000");
        // 组合查询条件
        BoolQueryBuilder must = QueryBuilders.boolQuery()
                .must(rangeQueryBuilder)
                .must(distanceQueryBuilder);
        
        
 		//条件2:按照距离排序
        //构建GeoDistanceSortBuilder设置按距离排序参数
        GeoDistanceSortBuilder sort = SortBuilders.geoDistanceSort("location", geoPoint);
        //升序排序
        sort.order(SortOrder.ASC);
      
        //构建检索
        SearchSourceBuilder sourceBuilder = SearchSourceBuilder
                .searchSource()
                .from(0)
                .size(10000)
                .query(must)
                .sort(sort);


        // 设置SearchRequest搜索参数
        searchRequest.source(sourceBuilder);

         log.info("开始搜索");
        // 执行ES请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        log.info("结束搜索");
        SearchHits hits = searchResponse.getHits();
        log.info("检索结果数量为:{}", "" + hits.getHits().length);
		//结果打印
        hits.forEach(hit -> {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            // 获取坐标
            Object location = sourceAsMap.get("location");

            String datadate = sourceAsMap.get("datadate").toString();

            Long id = Long.valueOf(sourceAsMap.get("id").toString());
            //获取距离值,并保留两位小数点
            BigDecimal geoDis = BigDecimal.valueOf((Double) hit.getSortValues()[0]);
            System.out.println("获取坐标:" + location + ",时间:" + datadate + ",距离:" + geoDis + ",id:" + id);
        });
    }
}
2023-08-20 23:16:51.745  INFO 8624 --- [           main] c.s.elasticsearch.TestSearchDocument     : 开始搜索
2023-08-20 23:16:52.705  INFO 8624 --- [           main] c.s.elasticsearch.TestSearchDocument     : 结束搜索
2023-08-20 23:16:52.706  INFO 8624 --- [           main] c.s.elasticsearch.TestSearchDocument     : 检索结果数量为:1401

索引数据规模大概1124W,搜索大概只需1秒左右 还可以进一步优化
在这里插入图片描述

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

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

相关文章

Map和Set—数据结构

文章目录 1.搜索1.1常见搜索方式1.2模型 2.map2.1介绍2.2 Map.Entry<K, V>2.3map的使用2.4遍历map2.5TreeMap和HashMap的区别 3.set3.1介绍3.2set的使用3.3遍历set3.4 TreeSet和HashSet的不同 4.搜索树4.1概念4.2实现4.3性能分析 5.哈希表5.1查找数据5.2冲突的概念5.3冲突…

如何批量加密PDF文件并设置不同密码 - 批量PDF加密工具使用教程

如果你正在寻找一种方法来批量加密和保护你的PDF文件&#xff0c;批量PDF加密工具是一个不错的选择。 它是一个体积小巧但功能强大的Windows工具软件&#xff0c;能够批量给多个PDF文件加密和限制&#xff0c;包括设置打印限制、禁止文字复制&#xff0c;并增加独立的打开密码。…

LAMP架构介绍配置命令讲解

LAMP架构介绍配置命令讲解 一、LAMP架构介绍1.1概述1.2LAMP各组件的主要作用1.3各组件的安装顺序 二、编译安装Apache httpd服务---命令讲解1、关闭防火墙&#xff0c;将安装Apache所需的软件包传到/opt/目录下2、安装环境依赖包3、配置软件模块4、编译安装5、优化配置文件路径…

数据的深海潜行:数据湖、数据仓库与数据湖库之间的微妙关系

导言&#xff1a;数据的重要性与存储挑战 在这个信息爆炸的时代&#xff0c;数据已经成为企业的核心资产&#xff0c;而如何高效、安全、便捷地存储这些数据&#xff0c;更是每个组织面临的重大挑战。 数据作为组织的核心资产 数据在过去的几十年里从一个辅助工具演变成企业的…

【JVM 内存结构 | 程序计数器】

内存结构 前言简介程序计数器定义作用特点示例应用场景 主页传送门&#xff1a;&#x1f4c0; 传送 前言 Java 虚拟机的内存空间由 堆、栈、方法区、程序计数器和本地方法栈五部分组成。 简介 JVM&#xff08;Java Virtual Machine&#xff09;内存结构包括以下几个部分&#…

【一】ubuntu20.04上搭建containerd版( 1.2.4 以上)k8s及kuboard V3

k8s 部署全程在超级用户下进行 sudo su本文请根据大纲顺序阅读&#xff01; 一、配置基础环境&#xff08;在全部节点执行&#xff09; 1、安装docker 使用apt安装containerd 新版k8s已经弃用docker转为containerd&#xff0c;如果要将docker改为containerd详见&#xff1a…

【K8S源码之Pod漂移】整体概况分析 controller-manager 中的 nodelifecycle controller(Pod的驱逐)

参考 k8s 污点驱逐详解-源码分析 - 掘金 k8s驱逐篇(5)-kube-controller-manager驱逐 - 良凯尔 - 博客园 k8s驱逐篇(6)-kube-controller-manager驱逐-NodeLifecycleController源码分析 - 良凯尔 - 博客园 k8s驱逐篇(7)-kube-controller-manager驱逐-taintManager源码分析 - 良…

多维时序 | MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测

多维时序 | MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测基本介绍模型特点程序设计参考资料 基本介绍 本次运行测试环境MATLAB2021b&#xff0c;MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测。代码说明&#xff1a…

Matplotlib数据可视化(五)

目录 1.绘制折线图 2.绘制散点图 3.绘制直方图 4.绘制饼图 5.绘制箱线图 1.绘制折线图 import matplotlib.pyplot as plt import numpy as np %matplotlib inline x np.arange(9) y np.sin(x) z np.cos(x) # marker数据点样式&#xff0c;linewidth线宽&#xff0c;li…

猿辅导Motiff亮相IXDC 2023国际体验设计大会,发布新功能获行业高度关注

近日&#xff0c;“IXDC 2023国际体验设计大会”在北京国家会议中心拉开序幕&#xff0c;3000设计师、1000企业、200全球商业领袖&#xff0c;共襄为期5天的用户体验创新盛会。据了解&#xff0c;此次大会是以“设计领导力”为主题&#xff0c;分享全球设计、科技、商业的前沿趋…

9.Sentinel哨兵

1.Sentinel Sentinel&#xff08;哨兵&#xff09;是由阿里开源的一款流量控制和熔断降级框架&#xff0c;用于保护分布式系统中的应用免受流量涌入、超载和故障的影响。它可以作为微服务架构中的一部分&#xff0c;用于保护服务不被异常流量冲垮&#xff0c;从而提高系统的稳定…

StreamingWarehouse的一些思考和未来趋势

300万字&#xff01;全网最全大数据学习面试社区等你来&#xff01; 一篇笔记。 以Hudi、Iceberg、Paimon这几个框架为例&#xff0c;它们支持高效的数据流/批读写、数据回溯以及数据更新。具备一些传统的实时和离线数仓不具备的特性&#xff0c;主要有几个方面&#xff1a; 这…

接口文档管理解决方案调研及Torna+Smart-doc的使用

文章目录 一、现状二、需求三、调研Swagger官方地址介绍 Knife4j官方地址介绍 Apifox官方地址介绍 Smart-doc Torna官方地址介绍 EasyYapi Yapi官方地址介绍 四、对比&#xff08;一&#xff09;Swagger1、部署方式2、优点3、缺点4、分享方式 &#xff08;二&#xff09;Knif…

VS+Qt 自定义Dialog

与QtCreator不同&#xff0c;刚用VS添加Qt Dialog界面有点懵&#xff0c;后整理了下&#xff1a; 1.右击项目&#xff0c;选择“添加-模块”&#xff0c;然后选择“Qt-Qt Widgets Class” 2.选择基类[1]QDialog,更改[2]ui文件名称&#xff0c;修改定义Dialog[3]对应类名&#…

学习Linux的注意事项(使用经验;目录作用;服务器注意事项)

本篇分享学习Linux过程中的一些经验 文章目录 1. Linux系统的使用经验2. Linux各目录的作用3. 服务器注意事项 1. Linux系统的使用经验 Linux严格区分大小写Linux中所有内容以文件形式保存&#xff0c;包括硬件&#xff0c;Linux是以管理文件的方式操作硬件 硬盘文件是/dev/s…

第4篇:vscode+platformio搭建esp32 arduino开发环境

第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloword第一个程序示范点亮板载LED 第3篇:vscode搭建esp32 arduino开发环境 1.配置默认安装路径&#xff0c;安装到D盘。 打开环境变量&#xff0c;点击新建 输入变量名PLATFORMIO_CORE_DIR与路径&#xff1a;D:\PLATF…

SpringBoot案例-配置文件-@ConfigurationProperties

问题分析 在往期的配置参数的文章中&#xff0c;对于阿里云OSS的参数时设置在yml配置文件中&#xff0c;然后使用Value&#xff08;”${}“&#xff09;对参数进行赋值&#xff0c;具体如下&#xff1a; 此种方法比较繁琐 问题解决 使用注解 Data 为变量自动生成get/set方…

游戏反外挂方案解析

近年来&#xff0c;游戏市场高速发展&#xff0c;随之而来的还有图谋利益的游戏黑产。在利益吸引下&#xff0c;游戏黑产扩张迅猛&#xff0c;已发展成具有庞大规模的产业链&#xff0c;市面上游戏受其侵扰的案例屡见不鲜。 据《FairGuard游戏安全2022年度报告》数据统计&…

IP协议报文结构

IP报文结构 4位版本号: 指定IP协议的版本, 对于IPv4来说, 就是4.4位头部长度: IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节.8位服务类型: 3位优先权字段(已经弃用) 4位TOS字段 1位保留字段(必须置为0). 4位…

C语言练习1(巩固提升)

C语言练习1 选择题 前言 “人生在勤&#xff0c;勤则不匮。”幸福不会从天降&#xff0c;美好生活靠劳动创造。全面建成小康社会的奋斗目标&#xff0c;为广大劳动群众指明了光明的未来&#xff1b;全面建成小康社会的历史任务&#xff0c;为广大劳动群众赋予了光荣的使命&…