一、先搞懂AWS上选数据库的核心逻辑

很多刚接触AWS做云原生应用的朋友,选数据库时特别懵:AWS上数据库服务有好几十个,名字还绕,到底该怎么挑?其实核心逻辑就一个——你要做的应用,到底“怕什么”“急什么”“要什么”。比如你做个给内部员工用的打卡工具,和做个面向全球用户的直播弹幕工具,选数据库的逻辑完全不一样。

先给大家明确一个前提:云原生应用的核心要求是“能快速扩容、能随时换机器、出问题能快速恢复”,所以选数据库不能光看功能,还要看它和AWS的云原生工具(比如容器、无服务器函数)能不能“搭得上”。

二、按应用场景拆的具体选择标准

2.1 场景一:做用户账号、订单这类“不能错”的核心数据

这类数据是应用的“命根子”,比如用户的手机号、订单的支付状态,绝对不能丢、不能乱,哪怕系统崩了,数据也得原封不动。

2.1.1 该选什么?

优先选AWS的关系型数据库服务(RDS),如果是小应用、不想管服务器,选RDS的无服务器版(RDS Serverless)更省心。

2.1.2 为什么?

关系型数据库天生就适合管“有规则”的数据:比如你能规定“用户的手机号必须是11位数字”“订单状态只能是‘待支付/已支付/已取消’”,不会出现乱填的情况。而且RDS有专门的备份机制,哪怕机房着火,数据也能找回来。

2.1.3 实际示例(技术栈:Node.js + RDS MySQL)

先说明:这个示例是一个简化的用户注册逻辑,用Node.js连RDS的MySQL实例,所有步骤都写得很细,新手也能跟着做。

第一步:先在AWS控制台开一个RDS MySQL实例(注意开的时候选“公开访问”,方便本地测试,正式环境要关),然后拿到实例的连接地址、用户名、密码。

第二步:在本地装Node.js,新建一个项目,装依赖:

# 装连接MySQL的工具包
npm install mysql2

第三步:写连接数据库的代码(把下面代码里的YOUR_RDS_ENDPOINT换成你自己的RDS地址,YOUR_DB_USER等换成对应的信息):

// 引入mysql2工具包
const mysql = require('mysql2/promise');

// 配置连接参数
const dbConfig = {
  host: 'YOUR_RDS_ENDPOINT', // RDS实例的连接地址,比如xxx.rds.amazonaws.com
  user: 'YOUR_DB_USER', // 你设置的数据库用户名
  password: 'YOUR_DB_PASSWORD', // 数据库密码
  database: 'user_db' // 你要操作的数据库名
};

// 写一个用户注册的函数
async function registerUser(phone, password) {
  let connection;
  try {
    // 第一步:连接数据库
    connection = await mysql.createConnection(dbConfig);
    console.log('数据库连接成功');

    // 第二步:先检查手机号有没有被注册(避免重复)
    const [rows] = await connection.query(
      'SELECT * FROM users WHERE phone = ?',
      [phone] // 把phone作为参数传进去,避免SQL注入
    );
    if (rows.length > 0) {
      return '手机号已被注册';
    }

    // 第三步:插入新用户数据(密码要加密,这里简化用md5,正式环境要用bcrypt)
    const hashedPassword = require('crypto').createHash('md5').update(password).digest('hex');
    await connection.query(
      'INSERT INTO users (phone, password, create_time) VALUES (?, ?, NOW())',
      [phone, hashedPassword]
    );
    return '注册成功';
  } catch (err) {
    console.error('操作出错:', err);
    return '注册失败,请稍后再试';
  } finally {
    // 不管成功失败,都要关闭连接,避免浪费资源
    if (connection) {
      await connection.end();
    }
  }
}

// 测试注册逻辑
registerUser('13800138000', '123456').then(res => console.log(res));

2.1.4 注意事项

  • 不要把数据库的密码直接写在代码里,正式环境要存在AWS的Secrets Manager里(专门存密码的服务),用代码动态拉取。
  • RDS默认是“主从”模式,主库用来写数据,从库用来读数据,能提高速度,但要注意从库的数据不是实时的(比如你刚改了密码,从库可能要等几秒才能看到新数据)。

2.2 场景二:做商品评论、用户动态这类“不那么怕错”的海量数据

这类数据量特别大,比如一个电商平台有几亿条商品评论,每条评论的重要性没那么高(哪怕丢几条,用户也不会发现),但要求存得快、查得快。

2.2.1 该选什么?

优先选AWS的NoSQL数据库,比如DynamoDB(专门给云原生做的,完全托管)。

2.2.2 为什么?

NoSQL数据库天生适合存“无规则”的海量数据:比如你可以给一条评论加“点赞数”“回复数”,给另一条加“晒图链接”,不用提前规定所有字段。而且DynamoDB能自动扩容,哪怕一天有100万条评论,它也能扛住,不用你手动加服务器。

2.2.3 实际示例(技术栈:Node.js + DynamoDB)

这个示例是简化的商品评论发布逻辑,用Node.js连DynamoDB,所有步骤都写得很细。

第一步:在AWS控制台开一个DynamoDB表,表名设为product_comments,主键设为comment_id(字符串类型)。

第二步:在本地装Node.js,新建一个项目,装依赖:

# 装AWS官方的DynamoDB工具包
npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb

第三步:写发布评论的代码(把下面代码里的YOUR_AWS_REGION换成你开DynamoDB的区域,比如us-east-1):

// 引入AWS的DynamoDB工具
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, PutCommand } = require('@aws-sdk/lib-dynamodb');

// 配置DynamoDB的连接参数
const client = new DynamoDBClient({
  region: 'YOUR_AWS_REGION', // 比如你开DynamoDB的区域是us-east-1
  credentials: {
    accessKeyId: 'YOUR_AWS_ACCESS_KEY', // 你的AWS访问密钥ID
    secretAccessKey: 'YOUR_AWS_SECRET_KEY' // 你的AWS秘密访问密钥
  }
});
const docClient = DynamoDBDocumentClient.from(client);

// 写一个发布评论的函数
async function publishComment(productId, userId, content) {
  try {
    // 生成唯一的评论ID(用时间戳加随机数,避免重复)
    const commentId = Date.now() + Math.floor(Math.random() * 1000);

    // 准备要存的评论数据
    const commentData = {
      comment_id: commentId.toString(),
      product_id: productId,
      user_id: userId,
      content: content,
      create_time: new Date().toISOString(),
      like_count: 0 // 初始点赞数为0
    };

    // 把数据存到DynamoDB
    const command = new PutCommand({
      TableName: 'product_comments',
      Item: commentData
    });
    await docClient.send(command);
    return '评论发布成功';
  } catch (err) {
    console.error('操作出错:', err);
    return '评论发布失败,请稍后再试';
  }
}

// 测试发布评论逻辑
publishComment('product_123', 'user_456', '这个商品质量很好').then(res => console.log(res));

2.2.4 注意事项

  • DynamoDB的主键是唯一的,如果你要查某个商品的所有评论,不能直接用商品ID查(因为商品ID不是主键),这时候要开“索引”(比如给product_id开一个二级索引),不然查起来特别慢。
  • DynamoDB的计费是按“读写次数”算的,如果你突然有大量请求(比如大促时),要注意开“自动扩容”,不然会被限流。

2.3 场景三:做直播弹幕、聊天消息这类“要实时”的临时数据

这类数据的特点是“实时性要求高”“生命周期短”:比如直播弹幕,用户刚发的,要立刻显示在所有人的屏幕上,而且弹幕不用存太久(比如存7天就够了)。

2.3.1 该选什么?

优先选AWS的Redis服务(ElastiCache for Redis),如果是小应用、不想管服务器,选ElastiCache的无服务器版(ElastiCache Serverless)。

2.3.2 为什么?

Redis是“内存数据库”,数据存在内存里,读写速度特别快(比关系型数据库快几十倍),特别适合做实时数据的缓存或临时存储。而且Redis有“过期时间”的功能,能自动删除旧数据,不用你手动清理。

2.3.3 实际示例(技术栈:Node.js + ElastiCache Redis)

这个示例是简化的直播弹幕发布逻辑,用Node.js连ElastiCache Redis,所有步骤都写得很细。

第一步:在AWS控制台开一个ElastiCache Redis集群,拿到连接地址、端口。

第二步:在本地装Node.js,新建一个项目,装依赖:

# 装连接Redis的工具包
npm install ioredis

第三步:写发布弹幕的代码(把下面代码里的YOUR_REDIS_ENDPOINT换成你自己的Redis地址,YOUR_REDIS_PORT换成端口):

// 引入ioredis工具包
const Redis = require('ioredis');

// 配置Redis的连接参数
const redis = new Redis({
  host: 'YOUR_REDIS_ENDPOINT', // ElastiCache Redis的连接地址
  port: YOUR_REDIS_PORT, // 端口,默认是6379
  db: 0 // 用第0个数据库
});

// 写一个发布弹幕的函数
async function publishDanmu(liveId, userId, content) {
  try {
    // 准备弹幕数据(转成JSON字符串,方便存)
    const danmuData = JSON.stringify({
      live_id: liveId,
      user_id: userId,
      content: content,
      create_time: new Date().toISOString()
    });

    // 把弹幕存到Redis,同时设置过期时间为7天(7*24*60*60秒)
    await redis.lpush(`danmu:${liveId}`, danmuData);
    await redis.expire(`danmu:${liveId}`, 7 * 24 * 60 * 60);

    // 只保留最新的1000条弹幕(避免Redis存太多数据)
    await redis.ltrim(`danmu:${liveId}`, 0, 999);

    return '弹幕发布成功';
  } catch (err) {
    console.error('操作出错:', err);
    return '弹幕发布失败,请稍后再试';
  }
}

// 测试发布弹幕逻辑
publishDanmu('live_789', 'user_456', '主播加油').then(res => console.log(res));

2.3.4 注意事项

  • Redis的数据是存在内存里的,如果集群重启,所有数据都会丢,所以不要用Redis存核心数据(比如用户密码)。
  • ElastiCache的Redis默认是“集群模式”,如果你要存大量数据,要注意分区,不然会出现数据分布不均的情况。

三、其他要考虑的细节

3.1 成本

AWS的数据库服务都是按使用量收费的,比如RDS的收费包括“服务器费用”“存储费用”“备份费用”,DynamoDB的收费包括“读写费用”“存储费用”,Redis的收费包括“内存费用”“网络费用”。如果你是小应用,尽量选无服务器版(比如RDS Serverless、DynamoDB On-Demand),不用的时候不花钱;如果是大应用,尽量选预留实例(提前买,能便宜很多)。

3.2 运维难度

如果你是个人开发者,尽量选完全托管的服务(比如DynamoDB、RDS Serverless),不用管服务器的升级、备份、扩容,AWS会帮你搞定;如果是团队开发者,有专门的运维人员,可以选需要自己管理的服务(比如EC2上装MySQL),成本更低。

3.3 兼容性

如果你之前的应用是用MySQL写的,想迁移到AWS,尽量选RDS的MySQL版,不用改代码;如果你之前的应用是用MongoDB写的,尽量选AWS的DocumentDB(和MongoDB兼容),不用改代码。

四、文章总结

选AWS上的数据库,核心是“匹配场景”:核心数据选RDS,海量非核心数据选DynamoDB,实时临时数据选Redis;同时要考虑成本、运维难度、兼容性。新手朋友可以先从无服务器版入手,成本低、不用管运维,等应用做大了再调整。