软件开发进阶技能之数据库进阶(六)

简介: 教程来源 https://bncne.cn/ 本节深入探讨NoSQL数据库与混合持久化架构:涵盖Redis高级用法(数据结构、RDB/AOF持久化、Sentinel/Cluster)、MongoDB索引与聚合,以及MySQL+Redis+Elasticsearch+Cassandra的电商混合存储实践,并通过游戏排行榜案例对比三种实现方案,强调性能、一致性与成本的平衡。

第七部分:NoSQL 数据库与混合持久化

关系型数据库并非万能,在特定场景下 NoSQL 数据库能提供更好的性能和灵活性。进阶开发者应当理解不同类型数据库的适用场景,并根据业务需求组合使用(混合持久化架构,Polyglot Persistence)。

7.1 常见 NoSQL 分类与选型
image.png
7.2 Redis 高级用法与持久化
Redis 不仅是缓存,还可以作为主数据库或消息队列。

7.2.1 数据结构的高级使用

# 哈希表存储对象(优于多 key)
HSET user:1001 name "Alice" age 30
HGETALL user:1001

# 有序集合做排行榜
ZADD leaderboard 100 "playerA" 95 "playerB"
ZREVRANGE leaderboard 0 2 WITHSCORES

# 位图统计日活(每个用户占用1位)
SETBIT login:2025-06-01 1001 1
BITCOUNT login:2025-06-01

7.2.2 持久化机制
RDB:快照方式,定时生成全量备份。恢复快但可能丢失最近一次快照后的数据。

AOF:追加写命令日志,更安全(可配置每秒 fsync),但文件体积大、恢复慢。

生产环境通常两者同时开启,或者使用 Redis Enterprise 的持久化方案。

7.2.3 高可用与集群
Redis Sentinel:提供主从自动切换,实现高可用。

Redis Cluster:分片方案,支持横向扩展,但部分跨 key 操作受限。

7.3 MongoDB 的索引与聚合
MongoDB 的索引机制类似关系数据库,但支持嵌套字段索引、地理空间索引、全文索引等。

聚合框架:替代复杂的分组和连接,通过管道($match, $group, $lookup)处理数据。例如,统计每个商品的销量前 10 的用户:

db.orders.aggregate([
    { $match: { status: "completed" } },
    { $group: { _id: { productId: "$product_id", userId: "$user_id" }, total: { $sum: "$amount" } } },
    { $sort: { total: -1 } },
    { $group: { _id: "$_id.productId", topUsers: { $push: { userId: "$_id.userId", total: "$total" } } } },
    { $project: { topUsers: { $slice: ["$topUsers", 10] } } }
]);

7.4 混合持久化架构示例
一个典型的电商系统可能同时使用:

MySQL:存储核心订单、用户账户(强事务、强一致性)。

Redis:缓存商品详情、用户 session、秒杀库存计数器。

Elasticsearch:商品搜索、日志分析(基于 Lucene 的搜索引擎,不是典型 NoSQL,但常与数据库配合)。

Cassandra:存储用户行为流水、点击流(写吞吐极高,可线性扩展)。

应用层通过业务规则决定数据写到哪里,并处理最终一致性问题(例如先写 MySQL,再异步同步到 Elasticsearch)。

第八部分:数据库进阶实战 —— 一个完整案例

我们以一个典型的“排名系统”为例,将上述知识串联起来。需求:一个游戏排行榜,记录每个玩家的得分,要求实时更新排名,并能高效查询前 100 名和玩家自己的排名。

8.1 方案一:关系数据库 + 索引优化
表结构:

CREATE TABLE scores (
    user_id INT PRIMARY KEY,
    score INT NOT NULL,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_score (score DESC)
);

查询前 100 名:

SELECT user_id, score FROM scores ORDER BY score DESC LIMIT 100;

查询某玩家排名:

SELECT COUNT(*) + 1 AS rank FROM scores WHERE score > (SELECT score FROM scores WHERE user_id = 123);

问题:COUNT 在大表下较慢;实时更新排名需要频繁写。适用于中等规模(千万以内)。

8.2 方案二:使用 Redis 有序集合

ZADD leaderboard 1500 playerA
ZADD leaderboard 2800 playerB
ZREVRANGE leaderboard 0 99 WITHSCORES    # 前100名
ZREVRANK leaderboard playerB             # 获取排名(0-based)

Redis 操作都是 O(log N),百万玩家轻松应对,且天然支持实时更新。但 Redis 内存昂贵,数据量太大时成本高。可以冷热分离:热数据(活跃玩家)放 Redis,冷数据(历史玩家)放 MySQL。

8.3 方案三:基于数据库的分区+缓存
如果坚持使用 MySQL,可以按 score 范围分区,例如每 1000 分一个分区,这样查询前 100 名只需扫描高分区的前几页。同时使用 Redis 作为查询缓存,score 更新时使缓存失效。

8.4 完整代码实现(应用层逻辑)
用 Python 展示排行榜服务的实现,包含缓存和降级:

import redis
import pymysql
import json

class LeaderboardService:
    def __init__(self):
        self.redis_client = redis.Redis(host='localhost', port=6379, db=0)
        self.db = pymysql.connect(host='localhost', user='app', password='xxx', database='game')

    def update_score(self, user_id, new_score):
        # 先更新数据库
        with self.db.cursor() as cursor:
            cursor.execute("INSERT INTO scores (user_id, score) VALUES (%s, %s) ON DUPLICATE KEY UPDATE score = %s",
                           (user_id, new_score, new_score))
            self.db.commit()
        # 再更新 Redis
        self.redis_client.zadd('leaderboard', {user_id: new_score})
        # 删除该用户的缓存排名(懒加载)
        self.redis_client.delete(f'rank:{user_id}')

    def get_top_n(self, n=100):
        # 优先从 Redis 读取,不存在则从 MySQL 回源并写入缓存
        cached = self.redis_client.get(f'top_{n}')
        if cached:
            return json.loads(cached)
        with self.db.cursor() as cursor:
            cursor.execute("SELECT user_id, score FROM scores ORDER BY score DESC LIMIT %s", (n,))
            rows = cursor.fetchall()
            result = [{'user_id': r[0], 'score': r[1]} for r in rows]
            # 缓存 60 秒,避免频繁穿透
            self.redis_client.setex(f'top_{n}', 60, json.dumps(result))
            # 同时预热 Redis ZSET(如果 Redis 内存允许)
            for r in rows:
                self.redis_client.zadd('leaderboard', {r[0]: r[1]})
        return result

    def get_user_rank(self, user_id):
        # 先尝试从 Redis ZSET 获取
        rank = self.redis_client.zrevrank('leaderboard', user_id)
        if rank is not None:
            return rank + 1
        # 降级查数据库
        with self.db.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) + 1 FROM scores WHERE score > (SELECT score FROM scores WHERE user_id=%s)", (user_id,))
            rank = cursor.fetchone()[0]
            # 回填到 Redis
            self.redis_client.zadd('leaderboard', {user_id: self._get_user_score_from_db(user_id)})
        return rank

请记住:数据库是系统的核心,任何疏忽都可能酿成严重事故。每次对数据库的变更(加索引、改表结构、调参数)都应该在测试环境验证,并有灰度上线和回滚方案。以敬畏之心对待数据,以科学之眼分析性能,你就能成为真正的数据库专家。
来源:
https://yvyus.cn/

相关文章
|
1月前
|
人工智能 运维 JavaScript
零基础入门教程:阿里云 Hermes Agent 一键部署完整流程详解(图文版)
随着AI智能体技术不断普及,Hermes Agent凭借出色的长对话记忆、复杂任务拆解、逻辑推理与多轮交互能力,成为个人办公、学习答疑、日常协作、智能辅助的热门开源工具。相较于普通对话机器人,Hermes Agent能够完整承接长链路任务、记住全程对话上下文,在深度交流、方案梳理、问题分析等场景表现尤为突出。
347 3
零基础入门教程:阿里云 Hermes Agent 一键部署完整流程详解(图文版)
|
1月前
|
数据采集 人工智能 运维
从报警风暴到主动免疫:吉利汽车智能运维落地实践
分享我们和阿里云 STAROps 一起,共建高质量智能运维的三步路径。
|
1月前
|
存储 人工智能 运维
本体论 Ontology 泛谈丨如何帮企业应对 Tokenmaxxing 困局
阿里云近期发布的全域智能运维平台 STAROps,将大模型技术、UModel、RCA、RCA benchmark 进行有机结合,是国内在 AIOps 方向上把 Ontology 落地得较为完整的实践。
426 17
|
1月前
|
人工智能 JavaScript 定位技术
CodeGraph+Hermes Agent组合部署构建代码地图教程:代码智能协同实操指南
在2026年编程AI工具高速发展的当下,各类编程Agent已经成为开发者日常工作的重要助手,无论是代码编写、问题排查、项目重构还是接口调试,AI智能体都能大幅降低人工成本。但在处理中大型代码仓库时,传统编程Agent普遍存在明显短板:需要反复调用文件读取、检索、目录查看等工具,不断遍历项目文件梳理代码结构,不仅消耗大量Token资源,还会拉长任务执行时长,工作效率大打降。而**CodeGraph**的出现完美解决了这一行业痛点,它依托AST语法树与本地知识图谱技术,提前为代码库构建结构化“代码地图”,让编程Agent无需重复探索项目结构。结合当下热门的Hermes Agent智能体框架,二者形
368 0
|
前端开发 Java 中间件
【AgentScope Java新手村系列】(3)工具系统
工具系统 — @Tool/@ToolParam 注解将 Java 方法注册为 Agent 能力,自主决定调用时机,支持同步/异步返回。
283 0
|
1月前
|
消息中间件 人工智能 运维
Agentic AICon【智能体基础设施与 AgentOps 专场】精彩回顾 & PPT 下载
Agentic AICon【智能体基础设施与 AgentOps 专场】精彩回顾 & PPT 下载。
|
1月前
|
JSON 运维 监控
Skills 是什么?Claude 官方教你做一个好用的 Skill
Skills 可以理解成 Claude Code 给 Agent 准备的任务经验包。它把一类任务里反复出现的说明、脚本、模板、配置、坑点和历史记录放在一起,让 Claude 下次遇到类似任务时,可以直接复用已有经验。
261 0
Skills 是什么?Claude 官方教你做一个好用的 Skill
|
1月前
|
机器学习/深度学习 人工智能 搜索推荐
书尖AI携手阿里云云端算力,打造智能阅读与轻量化学习新体验
书尖AI是基于阿里云算力的智能阅读工具,内嵌自研大模型,聚合亿万册正版资源。支持AI精读(3分钟提炼全书精华)、双人互动播客、个性化创作与智能语音生成,兼顾碎片听学与深度学习,操作简便、安全稳定。(239字)
|
1月前
|
人工智能 缓存 API
阿里云百炼api调用Qwen3.7-Max模型限时5折活动(免费领取100Tokens)
阿里云百炼推出Qwen3.7-Max模型API调用5折优惠,新用户免费领100万Tokens!该旗舰模型支持1M上下文、64K输出、256K思考预算,强化Agent能力,全面支持Function Calling、内置工具及批量调用,专为复杂工程与中文生产力场景优化。开通阿里云百炼:https://t.aliyun.com/U/fPVHqY
|
1月前
|
人工智能 运维 Linux
AI Agent进阶:从OpenClaw迁移至Hermes Agent全教程:安装、配置与实战及避坑指南
在AI智能体快速迭代的2026年,各类开源Agent框架逐步从基础工具调用向自进化、长效运行方向升级。OpenClaw作为早期热门AI智能体,凭借稳定的网关架构、丰富的插件生态收获大量用户,而同生态的**Hermes Agent**凭借独有的自进化学习闭环、分层记忆系统、更高的运行透明度,成为新一代优选框架。不少原有OpenClaw用户希望平滑迁移至Hermes Agent,同时保留历史配置、记忆内容与自定义技能。本文结合官方文档与实测经验,全面讲解两款框架的核心架构差异、前置调研要点、完整安装步骤、一键迁移流程、配置调试、多场景实战以及常见问题排查,全程兼顾零基础使用者与专业开发者,帮助用户
278 0