互联网浪潮中,科技改变生活,真切地让我们感受到工作的提效、生活的便利、娱乐的多样化。伴随更多的业务需求和极速的系统膨胀,作为核心价值的数据存储方案设计也变得愈发重要,NoSQL (Not only SQL) 也逐渐深入人心。亚马逊云科技秉承专门构建的理念,为客户提供完整的云原生数据战略体系,为不同业务类型,提供最优解。
01
Why DynamoDB?
自 2007 年的第一篇“Dynamo 研究论文”,到 2012 年 Amazon DynamoDB 服务的推出。现在,亚马逊云科技在大型非关系数据库和云服务技术领域 18 年持续投入,带给我们一款为互联网规模的应用程序而生、快速、高度可靠且具有成本效益的 NoSQL 数据库服务。
Amazon DynamoDB 是一种完全托管式、无服务器的 NoSQL 键值数据库,旨在运行任何规模的高性能应用程序。每天持续处理超过 10 万亿个请求。且可提供无限的可扩展性,稳定的个位数毫秒级性能和高达 99.999% 的可用性。
基于 Amazon DynamoDB 的能力和使用场景,如何以最佳实践的方式在 AI 场景发挥作用,是很多客户关心的话题。
02
业务场景描述
AIGC(AI-Generated Content,人工智能生成内容)风靡全球,而 LLM (Large Language Model) 创造力和智慧是最惊艳的部分。但是在工程化的过程中,我们希望数字人可以有“记忆”,来延续对话的上下文。那么会话的记忆存储,就需要一个可以承载高并发、低延迟的数据库来支撑业务。
2.1 架构图详解
根据业务需求,将 Amazon Bedrock 的 Claude2 模型和 Amazon DynamoDB 结合,来实现智能“问答”和“记忆”。
问答流程:
user 发起访问
基于 Amazon Elastic Kubernetes Service (Amazon EKS) 运行的 AI 数字人应用,接收对话请求
APP 查询 DynamoDB 会话的历史记录,并结合当前会话内容,整合信息
发送整合后信息到 Amazon Bedrock Claude2,获取“回答”
APP 发送“回答”给 user
03
数据查询/存储方案
在理清业务需求和技术实现架构之后,我们需要针对会话历史信息的存储和查询,进行详尽的技术拆解。
3.1 表设计和实体关系详解
聊天会话表用于记录用户和 AI 数字人之间的聊天 ID (chat_id)。
应用程序会根据用户 ID (user_id) 和 AI 数字人 (ai_id),获取当前#ACTIVE#的 chat_id。
用户可以选择删除旧的 chat_id(软删除,在数据库要保留这条记录,通过 delete_time 时间戳等信息来表示历史聊天)。
用户也可以重启聊天会话,同时删除旧的聊天会话,创建一个新的聊天会话。
因此,一个用户跟 AI 数字人之间允许有多条聊天会话记录,但是同一时间有且仅有一条处于活跃状态#ACTIVE#的聊天会话记录。
3.1.1 ERD(数据库实体关系图)
涉及的实体包括:用户(user_id),AI 数字人(ai_id),聊天会话(chat_id)
用户跟 AI 数字人之间是多对多的关系:
用户可以跟多个 AI 数字人存在多条聊天会话记录;
AI 数字人也可以跟多个用户存在多条聊天会话记录;
3.1.2 访问模式(聊天会话的增删改查)
创建新的聊天会话 – CreateChat
获取指定聊天会话 – GetChatByUser_Id_and_AI_Id
删除聊天会话 – DeleteChat
重启聊天会话 – RenewChat
更新指定会话 AI_Version – UpdateAIVersionByChat_Id
04
DynamoDB 数据建模&表格设计
4.1 表格设计
我们需要一个基表存储数据,同时需要一个 GSI (Global Secondary Index) 辅助查询。
基表名称:chat_session
全局二级索引名称:GSI1_chat(选择 Keys_Only 模式)
表格定义:
4.2 表格设计技巧
Amazon DynamoDB 是一个全托管,且简单易用的数据库。但是如何发挥其性能优势,也是需要我们知其善用。
这里我们就罗列一些小技巧:
有效利用 DynamoDB 排序键的特性:
例如标记活跃状态的 SK 前缀是#ACTIVE#,以#字符开头,让这条记录在排序过程中保持置顶。
兼顾业务和技术的 Key 设计:
场景 1. chat_id,我们可以使用 ULID (一种全局唯一且可以按字典序排序的标识符格式),其比随机 UUID 增加了时间戳,查询性能会更好。
场景 2. 在以 user_id & ai_id 作为查询条件,且以时间维度排序所有历史聊天会话的场景,ULID 就可以提供更好的查询性能。
4.3 表数据样例
基表插入数据后的样式
GSI 的数据样式
05
访问模式实现
在完成表格设计之后,如何消费数据,以满足业务需求?后续内容会详细介绍。
5.1 创建新的聊天会话 – CreateChat
在基表 chat_session 上执行 putItem 操作,通过条件判断表达式(ConditionExpression),确定当前表中不存在这条记录,才执行写入新的聊天会话。如果条件判断检查失败,则返回应用端 ConditionalCheckFailedException,表示数据库中存在这条记录。需要应用端做业务逻辑判断再操作。
- put_item_params = {
- 'TableName': 'chat_session',
- 'Item': {
- 'PK': {'S': user_id},
- 'SK': {'S': '#ACTIVE#' + ai_id},
- 'chat_id': {'S': chat_id},
- 'create_time': {'S': create_timestamp},
- 'GSI1PK': {'S': chat_id}
- },
- 'ConditionExpression': 'attribute_not_exists(PK) AND attribute_not_exists(SK)'
- }
5.2 获取指定聊天会话 –
GetChatByUser_Id_and_AI_Id
在基表 chat_session 上执行 getItem 操作,指定 PK=user_id and SK=#ACTIVE#ai_id,获取返回结果。
5.3 标记删除聊天会话 –
DeleteChat
组合操作完成这个场景,首先 getItem 获取到当前活跃聊天会话记录的所有属性。然后事务写入,插入一条有 delete_time 的历史会话记录,并删除当前活跃聊天会话记录。相关步骤参数见下面:
第一步:getItem PK=user_id and SK=#ACTIVE#ai_id, 可以复用上面的 getChatByUser_id_and_ai_id 函数。获取到这条 Item 所有信息记录下来。
第二步:事务写入
putItem PK=user_id and SK=ai_id#OLD#chat_id,其他属性包括 chat_id, ai_version,create_time,delete_time.
deleteItem PK=user_id and SK=#ACTIVE#ai_id
5.4 重新启动聊天会话 –
RenewChat
组合操作完成这个场景,跟上面软删除很类似,只是在事务写入时候,使用 updateItem。首先 getItem 获取到当前活跃聊天会话记录的所有属性。然后事务写入,插入一条有 delete_time 的历史会话记录,然后更新当前活跃聊天会话记录,为最新的 ai_version,chat_id。相关步骤参数见下面:
第一步:getItem PK=user_id and SK=#ACTIVE#ai_id, 可复用 getChatByUser_id_and_ai_id 函数。获取到这条 Item 所有信息记录下来。
第二步:事务写入
putItem PK=user_id and SK=ai_id#OLD#chat_id,其他属性包括 chat_id,ai_version,create_time,delete_time
updateItem PK=user_id and SK=#ACTIVE#ai_id,其他属性包括 chat_id,ai_version,create_time,GSI1PK
5.5 更新指定会话 AI_Version –
UpdateAIVersionByChat_Id
第一步:GSI1_chat 中 getItem PK=chat_id;拿到基表的 PK,SK
第二步:基表 chat_session 中 updateItem,PK=user_id,SK=#ACTIVE#ai_id
5.6 访问模式和实现方法汇总
为便于理解,我们将前面的访问模式,结合具体的实现方法,通过表格的形式进行汇总。
总结
通过以上内容,我们希望你理解“专门构建”的含义,不再根据数据库设计业务,而是通过业务选择适合的数据库。在类似场景下,DynamoDB 作为 Key-Value 数据库,可以充分发挥高并发、低延迟、高稳定性的特点,支撑核心业务的稳定运行。也希望通过本文,带来更清晰的 DynamoDB 的建模方法、建表模式,以及高性能查询的最佳实践。
参考链接
Amazon DynamoDB
https://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html
Gaming profile schema design in DynamoDB
https://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/data-modeling-schema-gaming-profile.html
本篇作者
许晓亮
亚马逊云科技解决方案架构师,负责基于亚马逊云科技云计算方案架构的咨询和设计,在国内推广亚马逊云科技云平台技术和各种解决方案。擅长数据库和大数据领域,结合云原生特性,为客户设计高效稳定的全球化系统方案。
李君
亚马逊云科技数据库解决方案技术专家,负责基于亚马逊云计算数据库产品的技术咨询与解决方案工作,特别专注于从 SQL 到 NoSQL 数据库的设计、测试、迁移、运维及优化等工作。
星标不迷路,开发更极速!
关注后记得星标「亚马逊云开发者」
听说,点完下面4个按钮
就不会碰到bug了!