基于 Flink 的淘宝实时数据管道设计:商品详情流式处理与异构存储

引言

在电子商务领域,实时数据处理能力已成为企业核心竞争力的重要组成部分。淘宝作为中国领先的电商平台,每天产生海量的商品数据,这些数据需要被实时处理、分析并分发到各种存储系统中,以支持搜索、推荐、库存管理等关键业务。本文将介绍基于 Apache Flink 构建的淘宝商品详情实时数据管道,探讨其架构设计、核心技术实现及异构存储集成方案。

系统架构设计

淘宝商品详情实时数据管道采用分层架构设计,主要包含以下几个部分:

  1. 数据采集层:负责从各个业务系统采集商品详情数据,主要通过 Canal 监听 MySQL binlog 和业务应用直接发送消息到 Kafka 实现
  2. 数据处理层:基于 Apache Flink 进行实时数据清洗、转换、富集和计算
  3. 数据存储层:将处理后的数据分发到异构存储系统,包括 Elasticsearch(搜索)、Redis(缓存)、MySQL(交易数据)和 HBase(历史归档)
  4. 监控告警层:监控整个数据管道的运行状态,及时发现并告警异常情况

架构图如下:

业务系统 → Kafka(接入层) → Flink(处理层) → 异构存储层(ES/Redis/MySQL/HBase)↓监控告警系统

核心技术实现

1. 环境准备与依赖配置

首先需要配置 Flink 项目依赖,主要包括 Flink 核心依赖、Kafka 连接器、各类存储系统连接器等。

<dependencies><!-- Flink Core --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-java</artifactId><version>1.14.4</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-streaming-java_2.12</artifactId><version>1.14.4</version></dependency><!-- Kafka Connector --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-kafka_2.12</artifactId><version>1.14.4</version></dependency><!-- Elasticsearch Connector --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-elasticsearch7_2.12</artifactId><version>1.14.4</version></dependency><!-- Redis Connector --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-redis_2.12</artifactId><version>1.1.5</version></dependency><!-- JDBC Connector for MySQL --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-jdbc_2.12</artifactId><version>1.14.4</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><!-- HBase Connector --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-hbase-2.2_2.12</artifactId><version>1.14.4</version></dependency><!-- JSON Processing --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.79</version></dependency>
</dependencies>

2. 商品数据模型定义

定义商品详情的数据模型,包含淘宝商品的核心属性:

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;public class ProductDetail {// 商品IDprivate Long productId;// 商品名称private String productName;// 商品价格private BigDecimal price;// 商品分类IDprivate Long categoryId;// 商品分类名称private String categoryName;// 商品描述private String description;// 商品图片URL列表private String[] imageUrls;// 商品属性键值对private Map<String, String> attributes;// 库存数量private Integer stock;// 销量private Integer salesCount;// 商家IDprivate Long sellerId;// 商家名称private String sellerName;// 上架时间private Date上架Time;// 数据更新时间private Date updateTime;// 数据来源private String dataSource;// 构造函数、getter和setter方法public ProductDetail() {}// Getters and Setterspublic Long getProductId() {return productId;}public void setProductId(Long productId) {this.productId = productId;}public String getProductName() {return productName;}public void setProductName(String productName) {this.productName = productName;}// 其他属性的getter和setter方法省略...@Overridepublic String toString() {return "ProductDetail{" +"productId=" + productId +", productName='" + productName + '\'' +", price=" + price +", updateTime=" + updateTime +'}';}
}

3. 实时数据管道核心实现

下面是基于 Flink 的商品详情实时数据管道核心代码实现,包括数据读取、处理和写入异构存储系统:

import org.apache.flink.api.common.functions.FilterFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction;
import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer;
import org.apache.flink.streaming.connectors.elasticsearch7.ElasticsearchSink;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;
import org.apache.flink.streaming.connectors.redis.RedisSink;
import org.apache.flink.streaming.connectors.redis.common.config.FlinkJedisPoolConfig;
import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommand;
import org.apache.flink.streaming.connectors.redis.common.mapper.RedisCommandDescription;
import org.apache.flink.streaming.connectors.redis.common.mapper.RedisMapper;
import org.apache.flink.streaming.api.functions.sink.RichSinkFunction;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.flink.connector.jdbc.JdbcConnectionOptions;
import org.apache.flink.connector.jdbc.JdbcSink;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.Requests;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;public class ProductDataPipeline {public static void main(String[] args) throws Exception {// 1. 初始化Flink执行环境final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.enableCheckpointing(5000); // 每5秒触发一次checkpoint// 2. 配置Kafka消费者Properties kafkaProps = new Properties();kafkaProps.setProperty("bootstrap.servers", "kafka-broker1:9092,kafka-broker2:9092");kafkaProps.setProperty("group.id", "product-detail-consumer-group");// 3. 从Kafka读取商品详情数据FlinkKafkaConsumer<String> kafkaConsumer = new FlinkKafkaConsumer<>("taobao-product-detail",  // Kafka主题new SimpleStringSchema(), // 反序列化器kafkaProps);// 设置从最早位置开始消费kafkaConsumer.setStartFromEarliest();// 创建输入数据流DataStream<String> rawDataStream = env.addSource(kafkaConsumer);// 4. 数据转换:JSON字符串 -> ProductDetail对象DataStream<ProductDetail> productStream = rawDataStream.map(new MapFunction<String, ProductDetail>() {@Overridepublic ProductDetail map(String jsonString) throws Exception {// 解析JSON字符串JSONObject json = JSON.parseObject(jsonString);// 转换为ProductDetail对象ProductDetail product = new ProductDetail();product.setProductId(json.getLong("productId"));product.setProductName(json.getString("productName"));product.setPrice(json.getBigDecimal("price"));product.setCategoryId(json.getLong("categoryId"));product.setCategoryName(json.getString("categoryName"));product.setDescription(json.getString("description"));product.setImageUrls(json.getJSONArray("imageUrls").toArray(new String[0]));product.setAttributes(json.getObject("attributes", Map.class));product.setStock(json.getInteger("stock"));product.setSalesCount(json.getInteger("salesCount"));product.setSellerId(json.getLong("sellerId"));product.setSellerName(json.getString("sellerName"));product.set上架Time(json.getDate("上架Time"));product.setUpdateTime(json.getDate("updateTime"));product.setDataSource(json.getString("dataSource"));return product;}})// 过滤无效数据.filter(new FilterFunction<ProductDetail>() {@Overridepublic boolean filter(ProductDetail product) throws Exception {return product.getProductId() != null && product.getProductName() != null && product.getPrice() != null;}});// 5. 数据处理:补充商品分类路径信息DataStream<ProductDetail> enrichedProductStream = productStream.map(new MapFunction<ProductDetail, ProductDetail>() {private Map<Long, String> categoryPathMap;@Overridepublic void open(Configuration parameters) throws Exception {super.open(parameters);// 实际应用中,这里可能从数据库或缓存加载分类路径信息categoryPathMap = new HashMap<>();categoryPathMap.put(1001L, "服饰鞋包>女装>连衣裙");categoryPathMap.put(1002L, "电子数码>手机>智能手机");// ... 更多分类}@Overridepublic ProductDetail map(ProductDetail product) throws Exception {// 补充分类路径信息到商品属性中String categoryPath = categoryPathMap.getOrDefault(product.getCategoryId(), "未知分类");product.getAttributes().put("categoryPath", categoryPath);return product;}});// 6. 写入异构存储系统// 6.1 写入Elasticsearch(用于商品搜索)configureEsSink(enrichedProductStream);// 6.2 写入Redis(用于热门商品缓存)configureRedisSink(enrichedProductStream);// 6.3 写入MySQL(用于交易和核心业务)configureMySqlSink(enrichedProductStream);// 6.4 写入HBase(用于历史数据归档)configureHBaseSink(enrichedProductStream);// 7. 执行Flink作业env.execute("Taobao Product Detail Real-time Pipeline");}/*** 配置Elasticsearch Sink*/private static void configureEsSink(DataStream<ProductDetail> productStream) {// 配置Elasticsearch节点Map<String, String> esConfig = new HashMap<>();esConfig.put("cluster.name", "taobao-es-cluster");esConfig.put("bulk.flush.max.actions", "1000");esConfig.put("hosts", "es-node1:9200,es-node2:9200");// 创建ElasticsearchSinkFunctionElasticsearchSinkFunction<ProductDetail> esSinkFunction = new ElasticsearchSinkFunction<ProductDetail>() {@Overridepublic void process(ProductDetail product, RuntimeContext ctx, RequestIndexer indexer) {// 构建索引请求Map<String, Object> json = new HashMap<>();json.put("productId", product.getProductId());json.put("productName", product.getProductName());json.put("price", product.getPrice());json.put("categoryId", product.getCategoryId());json.put("categoryName", product.getCategoryName());json.put("categoryPath", product.getAttributes().get("categoryPath"));json.put("description", product.getDescription());json.put("imageUrls", product.getImageUrls());json.put("attributes", product.getAttributes());json.put("stock", product.getStock());json.put("salesCount", product.getSalesCount());json.put("sellerId", product.getSellerId());json.put("sellerName", product.getSellerName());json.put("上架Time", product.get上架Time().getTime());json.put("updateTime", product.getUpdateTime().getTime());IndexRequest request = Requests.indexRequest().index("taobao_products").id(product.getProductId().toString()).source(json);indexer.add(request);}};// 创建并添加Elasticsearch SinkElasticsearchSink.Builder<ProductDetail> esSinkBuilder = new ElasticsearchSink.Builder<>(esConfig, esSinkFunction);productStream.addSink(esSinkBuilder.build());}/*** 配置Redis Sink*/private static void configureRedisSink(DataStream<ProductDetail> productStream) {// 配置Redis连接FlinkJedisPoolConfig redisConfig = new FlinkJedisPoolConfig.Builder().setHost("redis-node1").setPort(6379).setMaxTotal(20).build();// 创建RedisMapperRedisMapper<ProductDetail> redisMapper = new RedisMapper<ProductDetail>() {@Overridepublic RedisCommandDescription getCommandDescription() {// 使用Hash结构存储商品信息return new RedisCommandDescription(RedisCommand.HSET, "taobao:products");}@Overridepublic String getKeyFromData(ProductDetail product) {return product.getProductId().toString();}@Overridepublic String getValueFromData(ProductDetail product) {// 将商品信息序列化为JSON字符串return JSON.toJSONString(product);}};// 创建并添加Redis SinkRedisSink<ProductDetail> redisSink = new RedisSink<>(redisConfig, redisMapper);productStream.addSink(redisSink);}/*** 配置MySQL Sink*/private static void configureMySqlSink(DataStream<ProductDetail> productStream) {// MySQL连接配置String mysqlUrl = "jdbc:mysql://mysql-node1:3306/taobao_product_db?useSSL=false";String username = "db_user";String password = "db_password";// 创建JDBC SinkproductStream.addSink(JdbcSink.sink("INSERT INTO product_details " +"(product_id, product_name, price, category_id, category_name, " +"stock, sales_count, seller_id, update_time) " +"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) " +"ON DUPLICATE KEY UPDATE " +"product_name = VALUES(product_name), price = VALUES(price), " +"category_id = VALUES(category_id), category_name = VALUES(category_name), " +"stock = VALUES(stock), sales_count = VALUES(sales_count), " +"seller_id = VALUES(seller_id), update_time = VALUES(update_time)",(PreparedStatement stmt, ProductDetail product) -> {stmt.setLong(1, product.getProductId());stmt.setString(2, product.getProductName());stmt.setBigDecimal(3, product.getPrice());stmt.setLong(4, product.getCategoryId());stmt.setString(5, product.getCategoryName());stmt.setInt(6, product.getStock());stmt.setInt(7, product.getSalesCount());stmt.setLong(8, product.getSellerId());stmt.setTimestamp(9, new java.sql.Timestamp(product.getUpdateTime().getTime()));},new JdbcConnectionOptions.JdbcConnectionOptionsBuilder().withUrl(mysqlUrl).withUsername(username).withPassword(password).withDriverName("com.mysql.cj.jdbc.Driver").build()));}/*** 配置HBase Sink*/private static void configureHBaseSink(DataStream<ProductDetail> productStream) {productStream.addSink(new RichSinkFunction<ProductDetail>() {private Connection hbaseConnection;private Table productTable;@Overridepublic void open(Configuration parameters) throws Exception {super.open(parameters);// 配置HBase连接org.apache.hadoop.conf.Configuration hbaseConfig = HBaseConfiguration.create();hbaseConfig.set("hbase.zookeeper.quorum", "zk-node1,zk-node2,zk-node3");hbaseConfig.set("hbase.zookeeper.property.clientPort", "2181");hbaseConnection = ConnectionFactory.createConnection(hbaseConfig);productTable = hbaseConnection.getTable(TableName.valueOf("taobao:product_details"));}@Overridepublic void invoke(ProductDetail product, Context context) throws Exception {// 创建HBase Put对象Put put = new Put(Bytes.toBytes(product.getProductId().toString()));// 添加列族数据put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("product_name"),Bytes.toBytes(product.getProductName()));put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("price"),Bytes.toBytes(product.getPrice().toString()));put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("category_id"),Bytes.toBytes(product.getCategoryId().toString()));put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("category_name"),Bytes.toBytes(product.getCategoryName()));put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("update_time"),Bytes.toBytes(product.getUpdateTime().getTime()));// 插入数据productTable.put(put);}@Overridepublic void close() throws Exception {super.close();if (productTable != null) {productTable.close();}if (hbaseConnection != null) {hbaseConnection.close();}}});}
}

4. 数据倾斜处理与性能优化

在实际生产环境中,商品数据处理可能面临数据倾斜问题,特别是热门商品的更新频率远高于普通商品。针对这一问题,我们可以采取以下优化策略:

  1. 动态负载均衡:基于商品 ID 的哈希值动态调整 Flink 算子的并行度
  2. 热点分离:将热门商品与普通商品分离处理,热门商品采用更高的并行度
  3. 异步 I/O:使用 Flink 的 Async I/O 机制优化与外部存储系统的交互
  4. 状态后端优化:采用 RocksDB 作为状态后端,提高状态管理效率
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.partition.KeySelector;
import org.apache.flink.streaming.api.partitioning.FlinkPartitioner;// 优化的数据分区策略,解决热点问题
public class OptimizedProductPartitioner implements FlinkPartitioner<ProductDetail> {private static final long serialVersionUID = 1L;// 热门商品ID列表(实际应用中可动态加载)private static final Set<Long> HOT_PRODUCT_IDS = new HashSet<>();static {HOT_PRODUCT_IDS.add(100001L);HOT_PRODUCT_IDS.add(100002L);// 更多热门商品ID...}@Overridepublic int partition(ProductDetail product, int numPartitions) {// 对于热门商品,使用更多的分区来分散负载if (HOT_PRODUCT_IDS.contains(product.getProductId())) {// 热门商品使用后半部分的分区int hotStartPartition = numPartitions / 2;return hotStartPartition + (int)(product.getProductId() % (numPartitions - hotStartPartition));} else {// 普通商品使用前半部分的分区return (int)(product.getProductId() % (numPartitions / 2));}}
}// 在主程序中应用优化的分区策略
public class ProductDataPipelineOptimized {public static void main(String[] args) throws Exception {// 初始化环境...(同上)// 应用优化的分区策略DataStream<ProductDetail> rebalancedStream = enrichedProductStream.partitionCustom(new OptimizedProductPartitioner(), new KeySelector<ProductDetail, Long>() {@Overridepublic Long getKey(ProductDetail product) throws Exception {return product.getProductId();}});// 设置更高的并行度处理热门商品rebalancedStream.setParallelism(16);// 写入存储系统...(同上)env.execute("Optimized Taobao Product Detail Pipeline");}
}

监控与运维

为确保数据管道的稳定运行,需要建立完善的监控体系:

  1. Flink metrics 监控:监控作业的吞吐量、延迟、Checkpoint 成功率等关键指标
  2. 数据质量监控:对输入输出数据进行抽样检查,确保数据完整性和准确性
  3. 告警机制:当出现异常时(如数据延迟超过阈值、处理失败率上升等),通过邮件、短信等方式及时告警
  4. 自动恢复:配置 Flink 的 Savepoint 机制,在作业失败时能够快速恢复

结论与展望

基于 Flink 的淘宝商品详情实时数据管道实现了商品数据的实时采集、处理和分发,满足了电商平台对实时性的高要求。通过异构存储系统的集成,能够同时支持搜索、推荐、交易等多种业务场景。

未来,我们将在以下方面进行优化和扩展:

  1. 智能化路由:基于商品特性和业务需求,实现数据的智能路由和存储选择
  2. 流批一体:构建流批一体的数据处理架构,简化数据链路
  3. 实时分析:集成实时分析能力,支持商品热度、趋势等实时指标计算
  4. 多租户支持:优化架构以支持多租户模式,满足不同业务部门的个性化需求

该数据管道架构不仅适用于淘宝的商品详情处理,也可以推广到其他电商平台或需要实时处理异构数据的业务场景中。

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

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

相关文章

面试题:【多线程问题,三个线程A,B,C;C线程依赖B线程的结果执行,怎么控制】

在 Java 中&#xff0c;若需要控制线程间的依赖关系&#xff08;如 C 线程依赖 B 线程的结果&#xff09;&#xff0c;可以通过以下几种方式实现&#xff1a; 方案 1&#xff1a;使用 CountDownLatch CountDownLatch 是一个同步工具类&#xff0c;允许一个或多个线程等待其他线…

React useMemo 深度指南:原理、误区、实战与 2025 最佳实践

把“为什么用、怎么用、用错了怎么办”一次讲透&#xff0c;附 React 19 自动优化前瞻。一、useMemo 是什么&#xff1f; 一句话&#xff1a; useMemo 记住&#xff08;缓存&#xff09;昂贵计算结果&#xff0c;只在依赖变化时重新计算。 const memoValue useMemo(() > {…

[ HTML 前端 ] 语法介绍和HBuilderX安装

目录 一. HTML 1.概述 2. 安装前端开发工具 (1)HBuilderX下载 (2)创建html项目和使用 3. HTML基础 1.标签 (1).标签定义: (2).标签结构: (3).标签属性: 2.常用标签: 3.特殊符号: 4.表格(table) (1)基本标签: (2)基本结构: (3)表格属性: 5.表单(form) (1). 表单概述…

Spring Cloud系列—Alibaba Sentinel熔断降级

上篇文章&#xff1a; Spring Cloud系列— Alibaba Sentinel限流https://blog.csdn.net/sniper_fandc/article/details/149944260?fromshareblogdetail&sharetypeblogdetail&sharerId149944260&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link…

Spring Boot 使用 @NotBlank + @Validated 优雅校验参数

在日常开发中&#xff0c;我们常用 if (isBlank(...)) 来判断参数是否为空&#xff0c;但这种方式不仅繁琐&#xff0c;而且容易遗漏。 Spring 生态中推荐使用 JSR-303 校验注解&#xff08;NotBlank、NotNull 等&#xff09;配合 Validated 实现自动校验&#xff0c;大幅减少手…

网络安全(Java语言)简单脚本汇总 (一)

文章目录敏感信息探测脚本源代码思路URL批量存活探测器源代码思路端口扫描器源代码思路 敏感信息探测脚本 源代码/*** description 该脚本通过分析HTTP响应头&#xff0c;来检测可能暴露服务器信息的安全隐患*/import java.io.IOException; import java.net.HttpURLConnection;…

buuctf_NSBlogin_http_upload(极客2019+ACTF2020新生赛)

今天做三1个web 题目&#xff1a;NSB_login用户名有admin&#xff0c;看源码&#xff1a;I like rockyou&#xff01;今天学习到&#xff0c;kali里面有密码爆破的文件叫rockyou.txt&#xff08;/usr/share/wordlists/&#xff09;&#xff08;没kali也可以去https://gitcode.c…

IDEA如何引用brew安装的openjdk

因为 brew 安装的 openjdk@21 目录结构和 IDEA 期望的 JDK 目录不一样。所以默认brew安装的jdk,在IDEA中是无法识别到的。 一、创建软连接 sudo mkdir -p /Library/Java/JavaVirtualMachines sudo ln -sfn /usr/local/opt/openjdk@21/libexec/openjdk.jdk /Library/Java/Java…

【Unity3D】Spine黑线(预乘问题)、贴图边缘裁剪问题

一、黑线问题 Spine正确的导出和Unity导入设置&#xff08;解决黑边/彩条带问题&#xff09;_spine导出的图片有黑边-CSDN博客 采用&#xff08;已解决问题&#xff09; Texture 打包器启用 Premultiply alpha ,禁用Bleed Unity Texture 设置中禁用 sRGB (Color Texture) 和…

嵌入式系统学习Day18(文件编程-系统调用文件IO)

- open#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); 功能:打开文件 参数:pathname --- 文件名 flags 必选:O_RDONLYO_WRONLY…

Vue浅学

概述在最近的学习任务中了解了 Vue&#xff0c;并对其产生了浓厚的兴趣&#xff0c;现在分享一下我的学习所得关键字其一statestate 是 Vuex 存储中的“状态对象”&#xff0c;用于存储整个应用的共享数据&#xff08;如用户信息、令牌、权限等&#xff09;&#xff0c;比如&am…

机器翻译:Hugging Face库详解

文章目录一、Hugging Face概述1.1 Hugging Face介绍1.2 核心理念&#xff1a;模型即服务&#xff0c;但以开源形式二、核心架构2.1 Transformers库&#xff1a;模型交互的统一接口2.2 Datasets库&#xff1a;高效的数据处理引擎2.3 Tokenizers库&#xff1a;文本与模型的“翻译…

服务器安装gielab社区版

第一步&#xff1a;安装Gitlab 1,使用的是CentOs镜像(服务器最低配置为4核8g内存才行要不然带不动) 登录目标实例。 2,执行如下命令&#xff0c;安装所需依赖。 1 sudo yum install -y curl policycoreutils-python openssh-server 3,执行如下命令&#xff0c;启动SSH服务…

C#报错:System.NullReferenceException:“未将对象引用设置到对象的实例。”

C#使用自定义的类创建数组时&#xff0c;使用时报错&#xff0c;报错内容如下图&#xff1a;原因&#xff1a;C#中的数组是引用类型。当声明自定义类数组时&#xff0c;数组本身会被创建&#xff0c;但其元素&#xff08;即自定义类的实例&#xff09;默认未被实例化&#xff0…

Maven 的 module 管理

一、Maven 的 module 管理 1. 什么是 Maven module&#xff1f; Maven module&#xff08;模块&#xff09;&#xff0c;是 Maven 多模块项目结构&#xff08;multi-module project&#xff09;中的核心概念。它允许你将一个大型项目拆分为若干独立的小项目&#xff08;模块&am…

现在都是APP,小程序抢购,支持浏览器不支持 SSE

在 APP 和小程序抢购场景中&#xff0c;通常不原生支持SSE&#xff08;Server-Sent Events&#xff09;&#xff0c;这与浏览器对 SSE 的支持情况不同&#xff0c;具体如下&#xff1a;APP&#xff1a;一般情况下&#xff0c;APP 端不支持原生 SSE。若使用 UniApp 开发&#xf…

Spring Boot 深度解析:从原理到实践

一、Spring Boot 本质与核心价值 1.1 什么是 Spring Boot&#xff1f; Spring Boot 是 Spring 生态的革命性框架&#xff0c;旨在解决传统 Spring 开发的复杂性。它通过"约定优于配置"&#xff08;Convention Over Configuration&#xff09;理念&#xff0c;提供开箱…

WebSocket-java篇

问题引入消息推送的方式我们要实现&#xff0c;服务器把消息推送到客户端&#xff0c;可以轮训&#xff0c;长轮训还有sseWebSocket理论WebSocket 的由来与核心价值诞生背景&#xff1a;解决 HTTP 协议在实时通信中的固有缺陷&#xff08;单向请求-响应模式&#xff09;核心驱动…

用Python从零开始实现神经网络

反向传播算法用于经典的前馈人工神经网络。 它仍然是训练大型深度学习网络的技术。 在这个教程中&#xff0c;你将学习如何用Python从头开始实现神经网络的反向传播算法。 完成本教程后&#xff0c;您将了解&#xff1a; 如何将输入前向传播以计算输出。如何反向传播错误和…

算法148. 排序链表

题目&#xff1a;给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。示例 1&#xff1a;输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4] 示例 2&#xff1a;输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,3,4,5] 示例 3&a…