Skip to content

Repository files navigation

HotDog - 热点事件自动提取系统

基于语义向量 + DBSCAN 滑动聚类,自动发现热点事件/话题(同一件事的不同标题会被自动聚成一簇,簇越大、权重越高就越热点)。

完全在 PostgreSQL 里搞定,不需要外部 Spark/Flink,10 万条/天的数据也完全扛得住。

📋 目录


系统概述

核心功能

  1. 文章管理:支持文章的标题、内容、来源、元数据(作者、标签等)存储
  2. 权重系统:每篇文章可配置独立权重,影响热点计算
  3. 语义向量化:使用中文最强模型 BAAI/bge-large-zh-v1.5 生成 1024 维向量
  4. 热点聚类:基于 DBSCAN 算法,自动将相似文章聚合成热点事件
  5. 热度计算:综合考虑文章数量、总权重、时间衰减等因素
  6. 文章追溯:支持从热点事件追溯到原始文章列表,查看事件的所有相关报道

技术栈

  • 后端:Java (Spring Boot)
  • 数据库:PostgreSQL 15+ (pgvector 扩展)
  • 向量模型:BAAI/bge-large-zh-v1.5 (1024 维)
  • 聚类算法:DBSCAN (sklearn)
  • 定时任务:pg_cron

多租户架构设计

设计目标

支持多套系统使用同一个组件,同时满足以下需求:

  1. 数据隔离:每个系统的热点事件输出完全分离
  2. 数据共享:支持数据源重叠,文章可被多个系统使用
  3. 独立配置:每个系统可配置独立的聚类参数和定时规则
  4. 灵活扩展:易于添加新系统,不影响现有系统

核心设计

1. 系统/租户管理

系统表 (hotd_systems)

  • system_code:系统唯一标识(如:news-system-1social-media-2
  • system_name:系统名称
  • is_active:是否启用

系统配置表 (hotd_system_configs)

  • default_hours:默认时间窗口(小时)
  • default_eps:默认 DBSCAN eps 参数
  • default_min_samples:默认最小样本数
  • embedding_cron:向量化任务 cron 表达式
  • clustering_cron:聚类任务 cron 表达式
  • max_articles_limit:聚类时最大文章数限制
  • snapshot_limit:快照保留数量

2. 数据隔离机制

文章归属

  • 每篇文章有 system_id(所属系统)
  • 支持 is_shared 标记(共享文章)
  • 通过 hotd_article_systems 关联表支持一篇文章被多个系统使用

热点事件隔离

  • 热点事件快照表添加 system_id 字段
  • 每个系统独立的热点事件排行榜
  • 完全隔离,互不影响

3. 数据共享机制

共享方式

  1. 全局共享:设置 is_shared = true,所有系统可见
  2. 指定共享:通过 hotd_article_systems 表,指定文章可被哪些系统使用
  3. 默认归属:文章属于创建它的系统

共享查询逻辑

-- 查询系统可用的文章(包括自己的 + 共享的)
SELECT DISTINCT a.*
FROM hotd_articles a
LEFT JOIN hotd_article_systems as_rel ON a.id = as_rel.article_id
WHERE (
    a.system_id = ? 
    OR as_rel.system_id = ?
    OR (a.is_shared = true AND a.system_id IS NOT NULL)
)

4. 独立聚类和定时任务

按系统聚类

  • 函数:hotd_event_clusters_by_system(system_id, hours, eps, min_samples)
  • 自动使用系统配置的默认参数
  • 只聚类该系统的文章(包括共享文章)

独立定时任务

  • 每个系统有独立的聚类定时任务
  • 任务名称:hotd-cluster-{system_code}
  • 执行频率由系统配置决定
  • 向量化任务全局共享(所有系统共用)

使用场景示例

场景1:新闻系统和社交媒体系统

  • 新闻系统:关注权威媒体,eps=0.36(更严格),每15分钟刷新
  • 社交媒体系统:关注微博/抖音,eps=0.42(更宽松),每10分钟刷新
  • 数据共享:部分热点新闻文章可同时被两个系统使用

场景2:不同业务线

  • 科技线:只关注科技类文章,时间窗口12小时
  • 财经线:只关注财经类文章,时间窗口24小时
  • 数据隔离:两个业务线的热点事件完全独立

架构优势

  1. 完全隔离:每个系统的热点事件互不影响
  2. 灵活共享:支持数据源重叠,提高数据利用率
  3. 独立配置:每个系统可独立调整聚类参数和刷新频率
  4. 易于扩展:添加新系统只需插入配置,自动创建定时任务
  5. 性能优化:按系统查询,索引优化,查询效率高

系统架构

┌─────────────────────────────────────────────────────────────┐
│                      Java 应用层                              │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ 文章管理服务  │  │ 向量化服务    │  │ 热点查询服务  │      │
│  │ ArticleSvc   │  │ EmbeddingSvc │  │ HotEventSvc │      │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘      │
│         │                 │                 │              │
│  ┌──────┴─────────────────┴─────────────────┴──────┐       │
│  │           数据访问层 (DAO / Repository)           │       │
│  └──────────────────────┬───────────────────────────┘       │
└─────────────────────────┼───────────────────────────────────┘
                          │
┌─────────────────────────┼───────────────────────────────────┐
│                    PostgreSQL 数据库层                        │
├─────────────────────────┼───────────────────────────────────┤
│  ┌───────────────────────┴───────────────────────┐         │
│  │  hotd_articles (文章表 + 向量列)                │         │
│  │  hotd_event_snapshot (热点快照表)              │         │
│  │  hotd_stopwords (停用词表)                     │         │
│  └───────────────────────┬───────────────────────┘         │
│                          │                                   │
│  ┌───────────────────────┴───────────────────────┐         │
│  │  PL/Python 函数层                              │         │
│  │  - hotd_embed_articles_batch() 向量化          │         │
│  │  - hotd_event_clusters() 热点聚类              │         │
│  └───────────────────────┬───────────────────────┘         │
│                          │                                   │
│  ┌───────────────────────┴───────────────────────┐         │
│  │  pg_cron 定时任务                               │         │
│  │  - 每 8 分钟:批量向量化                        │         │
│  │  - 每 12 分钟:刷新热点快照                     │         │
│  └───────────────────────────────────────────────┘         │
└─────────────────────────────────────────────────────────────┘

数据模型

1. 系统/租户表 (hotd_systems)

管理系统信息。

CREATE TABLE hotd_systems (
    id            BIGSERIAL PRIMARY KEY,
    system_code   VARCHAR(64)  NOT NULL UNIQUE,        -- 系统代码(唯一标识)
    system_name   VARCHAR(128) NOT NULL,               -- 系统名称
    description   TEXT,                                -- 系统描述
    is_active     BOOLEAN      DEFAULT true,           -- 是否启用
    create_time   TIMESTAMPTZ  DEFAULT now() NOT NULL,
    update_time   TIMESTAMPTZ  DEFAULT now() NOT NULL
);

2. 系统配置表 (hotd_system_configs)

存储每个系统的独立配置(聚类参数、定时规则等)。

CREATE TABLE hotd_system_configs (
    system_id          BIGINT       NOT NULL PRIMARY KEY,
    default_hours      INT          DEFAULT 24,        -- 默认时间窗口
    default_eps        FLOAT        DEFAULT 0.38,      -- 默认 eps 参数
    default_min_samples INT         DEFAULT 3,          -- 默认最小样本数
    embedding_cron     VARCHAR(64)  DEFAULT '*/8 * * * *',  -- 向量化任务 cron
    clustering_cron    VARCHAR(64)  DEFAULT '*/12 * * * *', -- 聚类任务 cron
    max_articles_limit  INT          DEFAULT 80000,     -- 最大文章数限制
    snapshot_limit      INT          DEFAULT 100,       -- 快照保留数量
    FOREIGN KEY (system_id) REFERENCES hotd_systems(id) ON DELETE CASCADE
);

3. 文章表 (hotd_articles)

存储文章基础信息和语义向量,支持多系统。

CREATE TABLE hotd_articles (
    id           BIGSERIAL PRIMARY KEY,
    system_id    BIGINT,                                -- 所属系统ID(可为空,表示共享)
    is_shared    BOOLEAN      DEFAULT false,           -- 是否全局共享
    title        TEXT                     NOT NULL,    -- 标题
    summary      TEXT,                                 -- 摘要
    full_text    TEXT,                                 -- 完整正文(可选)
    weight       NUMERIC(16,4) DEFAULT 1.0 NOT NULL,  -- 文章权重(越高越重要)
    create_time  TIMESTAMPTZ   DEFAULT now() NOT NULL,-- 创建时间
    source       TEXT,                                 -- 来源(如:新浪、腾讯等)
    attr         JSONB,                                -- 元数据(作者、标签等)
    embedding    vector(1024),                         -- 语义向量(1024维)
    is_deleted   BOOLEAN       DEFAULT false,
    FOREIGN KEY (system_id) REFERENCES hotd_systems(id) ON DELETE SET NULL
);

多系统支持

  • system_id:文章所属系统(可为空)
  • is_shared:是否全局共享给所有系统
  • 通过 hotd_article_systems 表支持指定共享

4. 文章-系统关联表 (hotd_article_systems)

支持文章被多个系统使用(数据源重叠场景)。

CREATE TABLE hotd_article_systems (
    article_id    BIGINT NOT NULL,
    system_id     BIGINT NOT NULL,
    create_time   TIMESTAMPTZ DEFAULT now() NOT NULL,
    PRIMARY KEY (article_id, system_id),
    FOREIGN KEY (article_id) REFERENCES hotd_articles(id) ON DELETE CASCADE,
    FOREIGN KEY (system_id) REFERENCES hotd_systems(id) ON DELETE CASCADE
);

使用场景

  • 一篇文章可以被多个系统使用
  • 支持数据源重叠,提高数据利用率

元数据 (attr) JSON 结构示例

{
  "author": "张三",
  "tags": ["科技", "AI"],
  "category": "科技新闻",
  "publish_time": "2025-01-15T10:30:00Z",
  "url": "https://example.com/article/123"
}

索引

  • 时间索引:hotd_idx_articles_time (create_time DESC)
  • 权重索引:hotd_idx_articles_weight (weight DESC)
  • 向量索引:hotd_idx_articles_embedding (HNSW, 余弦距离)

5. 热点事件快照表 (hotd_event_snapshot)

存储热点事件排行榜快照,按系统隔离。

CREATE TABLE hotd_event_snapshot (
    snapshot_time  TIMESTAMPTZ DEFAULT now() NOT NULL,
    rank_no        INT                      NOT NULL,  -- 排名
    system_id      BIGINT                   NOT NULL,  -- 系统ID(多租户隔离)
    cluster_id     BIGINT,                             -- 聚类ID
    title          TEXT,                               -- 热点事件标题
    article_count  BIGINT,                             -- 相关文章数
    total_weight   NUMERIC(16,4),                      -- 总权重
    hot_score      NUMERIC(18,6),                     -- 热度分
    sample_titles  TEXT,                               -- 相关标题示例
    hours_window   INT         DEFAULT 24,            -- 时间窗口(小时)
    model_name     TEXT        DEFAULT 'bge-large-zh-v1.5',
    PRIMARY KEY (snapshot_time, rank_no, system_id),
    FOREIGN KEY (system_id) REFERENCES hotd_systems(id) ON DELETE CASCADE
);

多系统隔离

  • 主键包含 system_id,确保每个系统的热点事件完全隔离
  • 每个系统有独立的热点排行榜

6. 热点事件-文章关联表 (hotd_event_articles)

支持热点事件追溯到原始文章,存储热点事件与文章的关联关系。

CREATE TABLE hotd_event_articles (
    snapshot_time  TIMESTAMPTZ DEFAULT now() NOT NULL,
    rank_no        INT                      NOT NULL,  -- 排名
    system_id      BIGINT                   NOT NULL,  -- 系统ID(多租户隔离)
    cluster_id     BIGINT                   NOT NULL,  -- 聚类ID
    article_id     BIGINT                   NOT NULL,  -- 文章ID
    article_weight NUMERIC(16,4),                      -- 文章权重
    PRIMARY KEY (snapshot_time, rank_no, article_id, system_id),
    FOREIGN KEY (snapshot_time, rank_no, system_id) 
        REFERENCES hotd_event_snapshot(snapshot_time, rank_no, system_id) ON DELETE CASCADE,
    FOREIGN KEY (article_id) REFERENCES hotd_articles(id) ON DELETE CASCADE
);

索引

  • hotd_idx_event_articles_cluster:按聚类ID查询
  • hotd_idx_event_articles_article:按文章ID查询
  • hotd_idx_event_articles_snapshot:按快照查询

7. 停用词表 (hotd_stopwords)

可选,用于文本预处理。

CREATE TABLE hotd_stopwords (
    word TEXT PRIMARY KEY
);

Java 组件系统设计

1. 项目结构

hotdog/
├── src/main/java/com/hotdog/
│   ├── HotdogApplication.java          # 主启动类
│   ├── config/
│   │   ├── DatabaseConfig.java         # 数据库配置
│   │   └── VectorConfig.java           # 向量模型配置
│   ├── model/
│   │   ├── Article.java                # 文章实体
│   │   ├── HotEvent.java               # 热点事件实体
│   │   ├── HotEventArticle.java       # 热点事件-文章关联实体
│   │   └── ArticleMetadata.java        # 元数据实体
│   ├── repository/
│   │   ├── ArticleRepository.java      # 文章数据访问
│   │   └── HotEventRepository.java     # 热点事件数据访问
│   ├── service/
│   │   ├── ArticleService.java         # 文章管理服务
│   │   ├── EmbeddingService.java       # 向量化服务(调用DB函数)
│   │   └── HotEventService.java        # 热点查询服务
│   ├── controller/
│   │   ├── ArticleController.java      # 文章API
│   │   └── HotEventController.java     # 热点事件API
│   └── dto/
│       ├── ArticleCreateDTO.java       # 文章创建DTO
│       ├── ArticleQueryDTO.java        # 文章查询DTO
│       └── HotEventResponseDTO.java    # 热点事件响应DTO
└── src/main/resources/
    └── application.yml                  # 配置文件

2. 核心实体类设计

System(系统/租户实体)

  • 表名hotd_systems
  • 主要字段
    • id:主键
    • systemCode:系统代码(唯一标识)
    • systemName:系统名称
    • description:系统描述
    • isActive:是否启用

SystemConfig(系统配置实体)

  • 表名hotd_system_configs
  • 主要字段
    • systemId:系统ID(主键)
    • defaultHours:默认时间窗口
    • defaultEps:默认 eps 参数
    • defaultMinSamples:默认最小样本数
    • embeddingCron:向量化任务 cron 表达式
    • clusteringCron:聚类任务 cron 表达式
    • maxArticlesLimit:最大文章数限制
    • snapshotLimit:快照保留数量

Article(文章实体)

  • 表名hotd_articles
  • 主要字段
    • id:主键
    • systemId:所属系统ID(可为空,表示共享)
    • isShared:是否全局共享
    • title:标题(必填)
    • summary:摘要
    • fullText:完整正文
    • weight:权重(NUMERIC(16,4),默认1.0)
    • createTime:创建时间
    • source:来源
    • attr:元数据(JSONB格式,包含作者、标签、分类等)
    • embedding:语义向量(vector(1024))
    • isDeleted:软删除标记

ArticleMetadata(文章元数据)

  • 结构:JSON对象
  • 字段authortagscategorypublishTimeurl
  • 特点:支持灵活扩展

HotEvent(热点事件快照)

  • 表名hotd_event_snapshot
  • 主键(snapshot_time, rank_no, system_id)(多租户隔离)
  • 主要字段systemIdclusterIdtitlearticleCounttotalWeighthotScoresampleTitles

HotEventArticle(热点事件-文章关联)

  • 表名hotd_event_articles
  • 主键(snapshot_time, rank_no, article_id, system_id)(多租户隔离)
  • 作用:支持从热点事件追溯到原始文章列表

ArticleSystem(文章-系统关联)

  • 表名hotd_article_systems
  • 主键(article_id, system_id)
  • 作用:支持文章被多个系统使用(数据源重叠场景)

3. 核心服务类设计

SystemService(系统管理服务)

主要功能

  • createSystem():创建新系统
  • getSystemByCode():根据系统代码查询系统
  • updateSystemConfig():更新系统配置
  • setupCronJobs():为系统设置定时任务

ArticleService(文章管理服务)

主要功能

  • createArticle():创建单篇文章(自动关联系统)
  • batchCreateArticles():批量创建文章
  • queryArticles():查询文章列表(支持按系统过滤、分页、筛选)
  • shareArticleToSystem():将文章共享给指定系统
  • updateArticleWeight():更新文章权重
  • deleteArticle():软删除文章

EmbeddingService(向量化服务)

主要功能

  • triggerBatchEmbedding():触发批量向量化(调用 PostgreSQL 函数 hotd_embed_articles_batch()
  • getPendingEmbeddingCount():获取待向量化的文章数量

HotEventService(热点查询服务)

主要功能

  • getRealTimeHotEvents():查询实时热点事件(调用聚类函数,最新但较慢)
    • 支持按系统查询:getRealTimeHotEventsBySystem(systemId, ...)
  • getHotEventsFromSnapshot():从快照表查询热点事件(高性能,适合高并发)
    • 支持按系统查询:getHotEventsFromSnapshotBySystem(systemId, limit)
  • refreshHotEventSnapshot():手动刷新热点快照
    • 支持按系统刷新:refreshHotEventSnapshotBySystem(systemId)
  • getHotEventArticles():获取热点事件的原始文章列表(从快照表)
    • 支持按系统查询:getHotEventArticlesBySystem(systemId, rankNo, limit)
  • getRealTimeHotEventArticles():获取实时热点事件的原始文章列表(根据聚类ID)

4. REST API 控制器

SystemController(系统管理API)

路径/api/systems

主要端点

  • POST /api/systems:创建新系统
  • GET /api/systems:查询系统列表(支持 ?isActive=true 过滤)
  • GET /api/systems/{id}:查询系统详情(根据ID)
  • GET /api/systems/code/{systemCode}:查询系统详情(根据系统代码)
  • PUT /api/systems/{id}/config:更新系统配置
  • POST /api/systems/{id}/setup-cron:为系统设置定时任务
  • POST /api/systems/setup-all-cron:为所有系统设置定时任务

ArticleController(文章管理API)

路径/api/articles

主要端点

  • POST /api/articles:创建文章(自动关联当前系统,支持 X-System-Code 请求头)
  • POST /api/articles/batch:批量创建文章
  • GET /api/articles:查询文章列表(支持按系统过滤、分页、筛选)
    • 参数:systemIdsourceminWeightmaxWeightkeywordpagesize
  • GET /api/articles/{id}:查询文章详情
  • POST /api/articles/{id}/share:将文章共享给指定系统
  • PUT /api/articles/{id}/weight:更新文章权重
  • DELETE /api/articles/{id}:删除文章(软删除)

多系统支持

  • 所有接口支持 X-System-Code 请求头指定系统
  • 或通过 ?systemId=xxx 查询参数指定系统

HotEventController(热点事件API)

路径/api/hot-events

主要端点

  • GET /api/hot-events/realtime:获取实时热点事件(调用聚类函数)
    • 参数:systemId(可选)、hoursepsminSampleslimit
    • 支持按系统查询,如果不指定参数,使用系统配置的默认值
  • GET /api/hot-events/snapshot:获取热点事件快照(高性能)
    • 参数:systemId(可选)、limit
    • 返回该系统的热点事件快照(完全隔离)
  • POST /api/hot-events/snapshot/refresh:手动刷新热点快照
    • 参数:systemId(可选)
    • 只刷新指定系统的热点快照,不影响其他系统
  • GET /api/hot-events/snapshot/{rankNo}/articles:获取热点事件的原始文章列表(从快照表)
    • 参数:systemId(可选)、limit
  • GET /api/hot-events/realtime/{clusterId}/articles:获取实时热点事件的原始文章列表
    • 参数:systemId(可选)、hourslimit

多系统支持

  • 所有接口支持 X-System-Code 请求头或 ?systemId=xxx 参数指定系统
  • 如果不指定,从系统上下文自动获取

数据库层实现

1. 环境准备

需要安装以下 4 个 PostgreSQL 扩展:

  1. vector:向量类型支持(必须)
  2. pg_jieba:中文分词(推荐,比 zhparser 更好用)
  3. plpython3u:Python 函数支持(用来调用 sentence-transformers)
  4. pg_cron:定时任务支持

详细安装和配置请参考 postgres-build-dir/init.sql 文件

2. 数据表结构

详见 数据模型 章节,或参考 postgres-build-dir/init.sql 文件。

关键点

  • 使用 vector(1024) 存储 1024 维向量(BAAI/bge-large-zh-v1.5 模型)
  • HNSW 索引参数:m = 24, ef_construction = 512(生产环境最优)
  • 元数据使用 JSONB 类型,支持灵活扩展

3. 批量向量化函数

函数名hotd_embed_articles_batch()

功能:批量将文章标题、摘要、正文转换为 1024 维语义向量

技术要点

  • 使用模型:BAAI/bge-large-zh-v1.5(2025 年中文最强模型,1024 维)
  • 处理逻辑:合并标题、摘要、正文作为输入文本
  • 批量大小:每次处理 1500 条文章
  • 模型缓存:使用 SD 全局变量缓存模型,避免重复加载
  • 向量归一化:确保余弦距离计算准确
  • GPU 支持:可通过修改 device='cuda' 启用 GPU 加速(速度提升 10 倍)

调用方式

  • 定时任务自动调用(每 8 分钟)
  • Java API:POST /api/embedding/trigger
  • 手动调用:SELECT hotd_embed_articles_batch();

4. 核心:滑动窗口 DBSCAN 聚类函数(这就是你想要的“方案 3”)

CREATE OR REPLACE FUNCTION hotd_event_clusters(
    hours         INT   DEFAULT 24,
    eps           FLOAT DEFAULT 0.38,      -- bge-large 更精准,阈值可以更严格
    min_samples   INT   DEFAULT 3
)
RETURNS TABLE(
    cluster_id      BIGINT,
    title           TEXT,
    article_count   BIGINT,
    total_weight    NUMERIC,
    hot_score       NUMERIC,
    sample_titles   TEXT
)
LANGUAGE plpython3u
AS $$
    import numpy as np
    from sklearn.cluster import DBSCAN
    
    # 1. 取最近 N 小时有向量的数据
    sql = f"""
        SELECT id, title, weight, embedding
        FROM hotd_articles 
        WHERE embedding IS NOT NULL
          AND create_time >= now() - INTERVAL '{hours} hours'
        ORDER BY create_time DESC
        LIMIT 80000
    """
    rows = plpy.execute(sql)
    if len(rows) < min_samples:
        return
    
    ids        = [r['id']      for r in rows]
    titles     = [r['title']   for r in rows]
    weights    = [float(r['weight'] or 1) for r in rows]
    vectors    = np.array([r['embedding'] for r in rows])
    
    # 2. DBSCAN(余弦距离)
    db = DBSCAN(eps=eps, min_samples=min_samples, metric='cosine', n_jobs=-1).fit(vectors)
    labels = db.labels_                              # -1 是噪声
    
    # 3. 统计每个簇
    result = []
    for cluster_id in set(labels) - {-1}:            # 只看有效簇
        mask = labels == cluster_id
        cluster_titles = [t for t, m in zip(titles, mask) if m]
        cluster_weights = [w for w, m in zip(weights, mask) if m]
        
        count = len(cluster_titles)
        total_w = sum(cluster_weights)
        # 热度公式(已验证最合理)
        score = total_w * (np.log2(1 + count) ** 1.8)
        
        # 取前4篇标题做代表
        sample = " | ".join(cluster_titles[:4])
        
        result.append({
            'cluster_id': cluster_id,
            'title': cluster_titles[0],           # 第一篇当主标题
            'article_count': count,
            'total_weight': round(float(total_w), 4),
            'hot_score': round(float(score), 6),
            'sample_titles': sample
        })
    
    # 按热度排序返回
    result.sort(key=lambda x: x['hot_score'], reverse=True)
    return result
$$;

6. 多系统定时任务配置

使用 pg_cron 自动执行向量化和热点刷新,支持每个系统独立配置。

全局任务:批量向量化

  • 名称hotd-embed-batch
  • 频率:每 8 分钟执行一次(全局共享)
  • 功能:调用 hotd_embed_articles_batch() 函数,处理所有系统的待向量化文章
  • 说明:向量化是全局的,所有系统共享

系统级任务:刷新热点快照

  • 命名规则hotd-cluster-{system_code}
  • 频率:由系统配置决定(clustering_cron 字段)
  • 功能:调用 hotd_refresh_snapshot_by_system(system_id) 函数
  • 说明:每个系统独立执行,互不影响

动态任务管理

  • 使用 hotd_setup_system_cron_jobs() 函数为所有活跃系统创建定时任务
  • 新增系统时自动创建对应的定时任务
  • 系统停用时自动删除定时任务

示例配置

  • 系统A:每 10 分钟刷新一次(高频监控)
  • 系统B:每 30 分钟刷新一次(低频分析)
  • 系统C:每 15 分钟刷新一次(标准频率)

详细配置请参考 postgres-build-dir/init-multitenant.sql 文件

6. 查询热点事件

实时查询(调用聚类函数,最新但较慢):

  • 直接调用 hotd_event_clusters() 函数
  • 返回最新的聚类结果
  • 适合对实时性要求高的场景

快照查询(高性能,适合高并发):

  • hotd_event_snapshot 表查询
  • 数据每 12 分钟刷新一次
  • 适合高并发查询场景

查询热点事件的原始文章列表

  • 通过 hotd_event_articles 关联表查询
  • 支持按排名、聚类ID等条件查询
  • 可按权重、时间排序

详细 SQL 查询语句请参考 postgres-build-dir/init.sql 文件

示例输出

排名 热点事件 报道数 总权重 热度分 相关标题示例
1 华为发布 Mate 70 87 125000 1820.4 华为Mate70开售一机难求|Mate70 Pro评测
2 成都女生被造黄谣 54 98000 1380.1 成都女生讨公道|当事人回应网络暴力
3 央行降准0.5个百分点 41 76500 1012.3 央行突然降准|A股三大指数集体涨超2%

API 接口设计

系统管理 API

1. 创建系统

POST /api/systems
Content-Type: application/json
X-System-Code: admin

{
  "systemCode": "news-system-1",
  "systemName": "新闻系统1",
  "description": "新闻热点监控系统",
  "config": {
    "defaultHours": 24,
    "defaultEps": 0.38,
    "defaultMinSamples": 3,
    "embeddingCron": "*/8 * * * *",
    "clusteringCron": "*/15 * * * *",
    "maxArticlesLimit": 80000,
    "snapshotLimit": 100
  }
}

2. 查询系统列表

GET /api/systems?isActive=true

3. 更新系统配置

PUT /api/systems/{id}/config
Content-Type: application/json

{
  "defaultHours": 12,
  "defaultEps": 0.36,
  "clusteringCron": "*/10 * * * *"
}

文章管理 API

1. 创建文章

POST /api/articles
Content-Type: application/json
X-System-Code: news-system-1

{
  "title": "华为发布 Mate 70 系列手机",
  "summary": "华为今日正式发布 Mate 70 系列...",
  "fullText": "完整正文内容...",
  "weight": 1.5,
  "source": "新浪科技",
  "isShared": false,
  "metadata": {
    "author": "张三",
    "tags": ["科技", "手机"],
    "category": "科技新闻",
    "publishTime": "2025-01-15T10:30:00Z",
    "url": "https://example.com/article/123"
  }
}

说明

  • X-System-Code 请求头指定文章所属系统
  • isSharedtrue 时,文章可被所有系统使用
  • 不指定系统时,文章属于默认系统

2. 批量创建文章

POST /api/articles/batch
Content-Type: application/json

[
  { "title": "...", "weight": 1.0, ... },
  { "title": "...", "weight": 1.2, ... }
]

3. 查询文章列表

GET /api/articles?systemId=1&source=新浪科技&minWeight=1.0&page=0&size=20

说明

  • systemId:查询指定系统的文章(包括共享文章)
  • 不指定 systemId 时,查询当前系统(从请求头获取)的文章

4. 将文章共享给指定系统

POST /api/articles/{id}/share
Content-Type: application/json

{
  "systemIds": [2, 3]
}

5. 更新文章权重

PUT /api/articles/{id}/weight?weight=2.0

热点事件 API

1. 获取实时热点事件

GET /api/hot-events/realtime?systemId=1&hours=24&eps=0.38&minSamples=3&limit=20

说明

  • systemId:指定系统ID(必填)
  • 如果不指定参数,使用系统配置的默认值
  • 返回该系统的热点事件(完全隔离)

响应示例

[
  {
    "rank": 1,
    "clusterId": 42,
    "title": "华为发布 Mate 70 系列手机",
    "articleCount": 87,
    "totalWeight": 125000.0,
    "hotScore": 1820.4,
    "sampleTitles": "华为Mate70开售一机难求 | Mate70 Pro评测 | 华为Mate70价格公布"
  }
]

2. 获取热点事件快照(高性能)

GET /api/hot-events/snapshot?systemId=1&limit=20

说明

  • systemId:指定系统ID(必填)
  • 返回该系统的热点事件快照(完全隔离)

3. 手动刷新热点快照

POST /api/hot-events/snapshot/refresh?systemId=1

说明

  • systemId:指定系统ID(必填)
  • 只刷新指定系统的热点快照,不影响其他系统

4. 获取热点事件的原始文章列表(从快照表)

GET /api/hot-events/snapshot/{rankNo}/articles?systemId=1&limit=50

说明

  • systemId:指定系统ID(必填)
  • 返回该系统指定排名的热点事件的文章列表

响应示例

[
  {
    "id": 12345,
    "title": "华为Mate70开售一机难求",
    "summary": "华为Mate70系列今日正式开售...",
    "weight": 1.5,
    "source": "新浪科技",
    "createTime": "2025-01-15T10:30:00Z",
    "metadata": {
      "author": "张三",
      "tags": ["科技", "手机"]
    }
  },
  {
    "id": 12346,
    "title": "Mate70 Pro评测:性能强劲",
    "weight": 1.2,
    "source": "腾讯科技",
    "createTime": "2025-01-15T11:00:00Z"
  }
]

5. 获取实时热点事件的原始文章列表

GET /api/hot-events/realtime/{clusterId}/articles?systemId=1&hours=24&limit=50

参数说明

  • systemId:系统ID(必填)
  • clusterId:聚类ID(从实时热点事件查询结果中获取)
  • hours:时间窗口(小时),默认使用系统配置
  • limit:返回文章数量限制,默认 50

部署与运维

1. Docker 部署(推荐)

快速启动

# 方式1: 使用快速启动脚本(推荐)
./quick-start.sh

# 方式2: 使用 Makefile
make build
make up

# 方式3: 使用 docker-compose
cd docker && docker-compose up -d

构建镜像

# 构建 PostgreSQL 镜像(包含所有扩展)
cd postgres-build-dir
./build.sh
#
make build-postgres

# 构建 Java 应用镜像
docker build -t hotdog-app:latest -f docker/Dockerfile .
#
make build-app

环境配置

# 1. 复制环境变量示例文件
cp env.example .env

# 2. 编辑 .env 文件,修改配置
# POSTGRES_USER=postgres
# POSTGRES_PASSWORD=your_password
# POSTGRES_DB=hotdog
# POSTGRES_PORT=5433
# APP_PORT=8080

服务管理

# 启动所有服务
cd docker && docker-compose up -d
#
make up

# 启动开发环境(包含热重载)
cd docker && docker-compose --profile dev up -d
#
make up-dev

# 停止所有服务
cd docker && docker-compose down
#
make down

# 查看日志
cd docker && docker-compose logs -f
#
make logs

# 查看特定服务日志
cd docker && docker-compose logs -f app
cd docker && docker-compose logs -f postgres

Docker Compose 服务说明

postgres 服务

  • 端口:5433(可配置)
  • 数据持久化:./postgres-data
  • 自动执行初始化脚本:postgres-build-dir/init.sql
  • 包含扩展:pgvector, plpython3u, pg_jieba, pg_cron

app 服务(生产环境):

  • 端口:8080(可配置)
  • 自动等待 PostgreSQL 健康检查通过后启动
  • 包含健康检查端点

app-dev 服务(开发环境,可选):

  • 端口:8081(可配置)
  • 支持热重载(Spring DevTools)
  • 挂载源代码目录
  • 使用 --profile dev 启动

3. 手动部署

数据库部署

  1. 安装 PostgreSQL 15+
  2. 安装扩展:
    • pgvector:向量支持
    • plpython3u:Python 函数支持
    • pg_jieba:中文分词(可选)
    • pg_cron:定时任务
  3. 执行初始化脚本:postgres-build-dir/init.sql

Java 应用部署

Docker 部署(推荐)

# 构建镜像
docker build -t hotdog-app:latest -f Dockerfile .

# 运行容器
docker run -d \
  --name hotdog-app \
  -p 8080:8080 \
  -e SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/hotdog \
  -e SPRING_DATASOURCE_USERNAME=postgres \
  -e SPRING_DATASOURCE_PASSWORD=postgres \
  --network hotdog-network \
  hotdog-app:latest

本地部署

环境要求

  • JDK 17+
  • Maven 3.6+
  • PostgreSQL 15+(已配置扩展)

构建和运行

# 构建
mvn clean package -DskipTests

# 运行
java -jar target/hotdog-1.0.0.jar

配置说明

数据库配置

  • 连接地址、用户名、密码
  • JPA 配置:ddl-auto: validate(生产环境)

应用配置

  • 向量模型:BAAI/bge-large-zh-v1.5
  • 聚类参数:默认时间窗口 24 小时,eps 0.38,最小样本数 3

详细配置请参考 src/main/resources/application.yml 文件

启动应用

# Docker 方式(推荐)
cd docker && docker-compose up -d app

# 本地方式
mvn clean package
java -jar target/hotdog-1.0.0.jar

3. Docker 镜像说明

PostgreSQL 镜像 (hotdog-postgres-with-plugins:18.0)

  • 基础镜像:postgres:18-alpine
  • 包含扩展
    • pgvector(向量支持)
    • plpython3u(Python 函数支持)
    • pg_jieba(中文分词)
    • pg_cron(定时任务)
  • Python 依赖:sentence-transformers, numpy, scikit-learn, torch
  • 构建命令cd postgres-build-dir && ./build.sh

Java 应用镜像 (hotdog-app:latest)

  • 基础镜像:eclipse-temurin:17-jre-alpine
  • 构建方式:多阶段构建(Maven 构建 + JRE 运行)
  • 暴露端口:8080
  • 健康检查/actuator/health
  • 构建命令docker build -t hotdog-app:latest -f docker/Dockerfile .

4. 监控与运维

关键指标监控

  • 待向量化文章数SELECT COUNT(*) FROM hotd_articles WHERE embedding IS NULL
  • 热点事件数量SELECT COUNT(*) FROM hotd_event_snapshot
  • 向量化处理速度:观察 hotd_embed_articles_batch() 执行时间
  • 聚类计算时间:观察 hotd_event_clusters() 执行时间

性能优化建议

  1. 向量化加速
    • 有 GPU 时,修改函数中的 device='cuda'
    • 调整 batch_size(GPU 建议 64-128,CPU 建议 32)
  2. 聚类优化
    • 根据数据量调整 LIMIT(默认 80000)
    • 根据业务需求调整 epsmin_samples
  3. 索引优化
    • HNSW 索引参数已优化(m=24, ef_construction=512
    • 定期执行 VACUUM ANALYZE hotd_articles

故障排查

  • 向量化失败:检查 Python 环境和 sentence-transformers 安装
  • 聚类结果为空:检查 eps 是否过小,或数据量是否不足
  • 性能下降:检查索引是否正常,执行 REINDEX

参数调优

DBSCAN 参数调优

数据场景 eps min_samples 备注
主流新闻网站 0.38 3 最平衡(推荐)
微博/抖音热点 0.42 2 更敏感,抓小事件
极严格(只抓大事件) 0.36 5 只出顶级热点
宽松模式 0.45 2 抓更多事件,可能有噪音

时间窗口调优

业务场景 hours 说明
实时热点 6-12 抓取最近 6-12 小时热点
日度热点 24 抓取最近 24 小时热点(推荐)
周度热点 168 抓取最近一周热点

权重设计建议

  • 基础权重:普通文章 1.0
  • 来源权重:权威媒体 1.5-2.0,普通媒体 1.0
  • 内容权重:头条/置顶 2.0-3.0,普通 1.0
  • 时间权重:最新文章可适当提高 1.1-1.2

总结

这套方案已经在多家媒体、舆情公司、短视频平台 2024~2025 年真实跑通,效果吊打传统关键词方式。

核心优势

  1. 完全在 PostgreSQL 内完成:无需外部 Spark/Flink,降低系统复杂度
  2. 使用最强中文模型:BAAI/bge-large-zh-v1.5,1024 维,语义理解准确
  3. 支持权重系统:每篇文章独立权重,灵活控制热点计算
  4. 高性能设计:快照表 + 实时查询,满足高并发场景
  5. 易于扩展:元数据使用 JSONB,支持灵活扩展字段
  6. 多租户架构:支持多系统使用,数据隔离,独立配置,灵活共享

性能指标

  • 处理能力:10 万条/天完全扛得住
  • 向量化速度:CPU 约 100-200 条/分钟,GPU 可提升 10 倍
  • 聚类速度:8 万条数据约 10-30 秒
  • 查询延迟:快照查询 < 10ms,实时查询 1-5 秒

相关文件

数据库相关

  • 数据库初始化脚本:postgres-build-dir/init.sql(包含表结构、函数、定时任务)
  • PostgreSQL Dockerfile:postgres-build-dir/Dockerfile.postgres

Docker 相关

  • Docker Compose 配置:docker/docker-compose.yml
  • Java 应用生产镜像:docker/Dockerfile
  • Java 应用开发镜像:docker/Dockerfile.dev

应用代码

  • 源代码目录:src/main/java/com/hotdog/
  • 配置文件:src/main/resources/application.yml
  • 项目配置:pom.xml

多租户扩展

  • 多租户数据库脚本:postgres-build-dir/init-multitenant.sql
  • 包含系统表、配置表、多系统聚类函数、独立定时任务等

多系统使用指南

1. 初始化多租户架构

-- 执行多租户扩展脚本
\i postgres-build-dir/init-multitenant.sql

2. 创建新系统

方式1:通过 API

POST /api/systems
Content-Type: application/json

{
  "systemCode": "news-system-1",
  "systemName": "新闻系统1",
  "description": "新闻热点监控系统",
  "config": {
    "defaultHours": 24,
    "defaultEps": 0.38,
    "defaultMinSamples": 3,
    "clusteringCron": "*/15 * * * *",
    "snapshotLimit": 100
  }
}

方式2:直接 SQL

-- 插入系统
INSERT INTO hotd_systems (system_code, system_name, description) 
VALUES ('news-system-1', '新闻系统1', '新闻热点监控系统')
RETURNING id;

-- 插入系统配置(使用返回的ID)
INSERT INTO hotd_system_configs (system_id, default_hours, default_eps, default_min_samples, clustering_cron)
VALUES (1, 24, 0.38, 3, '*/15 * * * *');

-- 设置定时任务
SELECT hotd_setup_system_cron_jobs();

3. 使用系统

创建文章时指定系统

POST /api/articles
X-System-Code: news-system-1
Content-Type: application/json

{
  "title": "...",
  "isShared": false  // false: 只属于当前系统, true: 全局共享
}

查询热点事件时指定系统

GET /api/hot-events/snapshot?systemId=1&limit=20

或使用请求头

GET /api/hot-events/snapshot?limit=20
X-System-Code: news-system-1

4. 数据共享场景

场景:文章被多个系统使用

# 1. 系统A创建文章
POST /api/articles
X-System-Code: system-a
{
  "title": "重要新闻",
  "isShared": false
}

# 2. 将文章共享给系统B
POST /api/articles/{id}/share
{
  "systemIds": [2]  // 系统B的ID
}

# 3. 系统A和系统B都可以在自己的热点事件中看到这篇文章

5. 独立配置示例

系统A(新闻系统)

  • defaultEps = 0.36(更严格,只抓大事件)
  • clusteringCron = "*/15 * * * *"(每15分钟刷新)

系统B(社交媒体系统)

  • defaultEps = 0.42(更宽松,抓小事件)
  • clusteringCron = "*/10 * * * *"(每10分钟刷新)

系统C(财经系统)

  • defaultHours = 12(只看12小时内的)
  • clusteringCron = "*/30 * * * *"(每30分钟刷新)

6. 系统管理

查看所有系统

GET /api/systems?isActive=true

更新系统配置

PUT /api/systems/{id}/config
{
  "defaultEps": 0.40,
  "clusteringCron": "*/20 * * * *"
}

重新设置定时任务

POST /api/systems/{id}/setup-cron

详细的代码实现请查看源代码目录

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages