系列篇章💥

No. 文章
1 LangChain4j Java AI 应用开发实战(一):LangChain4j 快速入门指南
2 LangChain4j Java AI 应用开发实战(二):大模型参数调优实战:Temperature、TopP、MaxTokens 深度解析
3 LangChain4j Java AI 应用开发实战(三):多模态 AI 开发 - 图片理解与图像生成实战
4 LangChain4j Java AI 应用开发实战(四):提示词工程进阶 - 模板化与结构化 Prompt 设计
5 LangChain4j Java AI 应用开发实战(五):流式响应与对话记忆 - 提升用户体验的关键技术
6 LangChain4j Java AI 应用开发实战(六):声明式 AI Service - LangChain4j 的核心编程模型
7 LangChain4j Java AI 应用开发实战(七):结构化输出实战 - 从非结构化文本提取 POJO 对象
8 LangChain4j Java AI 应用开发实战(八):用户隔离与持久化记忆 - 企业级对话系统设计


前言

单用户对话系统很简单,但企业级应用需要支持成千上万用户同时交互,每个用户的对话历史必须严格隔离、重启不丢失。如何实现多用户记忆管理?如何选择合适的持久化方案?本文将深入讲解 LangChain4j 的 @MemoryId 注解实现用户隔离、ChatMemoryProvider 动态创建记忆实例、以及从内存到 MySQL/Redis 的多种持久化方案。你将学会构建支持高并发的多用户对话系统,掌握会话 ID 生成策略、数据清理机制、线程安全控制等企业级设计技巧,让 AI 应用真正具备生产环境部署能力。


一、为什么需要用户隔离?

1.1 单用户记忆的局限

回顾之前的示例,我们使用单一 ChatMemory

// ❌ 单用户记忆:所有对话共享同一个记忆
ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);

Assistant assistant = AiServices.builder(Assistant.class)
    .chatModel(model)
    .chatMemory(chatMemory)  // 全局共享
    .build();

问题场景

用户 A:我叫张三
AI:你好,张三!

用户 B:我叫李四
AI:你好,李四!

用户 A:我叫什么名字?
AI:你叫李四。  ← ❌ 错误!记忆被用户 B 覆盖

原因:所有用户共享同一个 ChatMemory,对话历史相互干扰。

1.2 多用户隔离的需求

企业级应用需要:

需求 说明 示例
记忆隔离 每个用户独立记忆 用户 A 看不到用户 B 的对话
持久化存储 重启不丢失 用户下次登录保留历史
并发访问 支持多用户同时交互 1000 个用户同时聊天
资源控制 限制单个用户占用 每用户最多 100 条消息
数据清理 自动删除过期数据 30 天未活跃则清除

二、用户隔离:@MemoryId 注解

2.1 完整代码解析

public class ServiceWithMemoryForEachUserExample {

    interface Assistant {

        /**
         * @MemoryId 标识用户 ID,用于隔离不同用户的对话记忆
         */
        String chat(@MemoryId int memoryId, @UserMessage String userMessage);
    }

    public static void main(String[] args) {

        ChatModel model = OpenAiChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .modelName("gpt-4o-mini")
                .apiKey("demo")
                .build();

        // 构建支持多用户的 AI 助手
        Assistant assistant = AiServices.builder(Assistant.class)
                .chatModel(model)
                // 记忆提供者:为每个 memoryId 动态创建独立记忆
                .chatMemoryProvider(memoryId -> 
                    MessageWindowChatMemory.withMaxMessages(10)
                )
                .build();

        // 用户 1(Klaus)的第一次对话
        System.out.println(assistant.chat(1, "Hello, my name is Klaus"));
        // 输出:Hi Klaus! How can I assist you today?

        // 用户 2(Francine)的第一次对话
        System.out.println(assistant.chat(2, "Hello, my name is Francine"));
        // 输出:Hello Francine! How can I assist you today?

        // 用户 1 询问姓名(能记住)
        System.out.println(assistant.chat(1, "What is my name?"));
        // 输出:Your name is Klaus.

        // 用户 2 询问姓名(不受影响)
        System.out.println(assistant.chat(2, "What is my name?"));
        // 输出:Your name is Francine.
    }
}

运行结果

Hi Klaus! How can I assist you today?
Hello Francine! How can I assist you today?
Your name is Klaus. How can I help you today, Klaus?
Your name is Francine. How can I help you today?

关键点:用户 1 和用户 2 的记忆完全隔离,互不干扰。

2.2 核心概念解析

(1)@MemoryId 注解

String chat(@MemoryId int memoryId, @UserMessage String userMessage);

作用

  • 标记哪个参数作为用户/会话 ID
  • LangChain4j 根据该 ID 查找或创建对应的 ChatMemory
  • 相同 ID 复用同一记忆,不同 ID 独立记忆

支持的类型

类型 适用场景 示例
int/long 数据库用户 ID userId = 12345
String UUID、邮箱、手机号 "user-abc-123"
Object 自定义对象(需重写 hashCode new UserSession(...)

推荐:使用业务相关的唯一标识(如用户 ID、会话 ID)。

(2)ChatMemoryProvider

.chatMemoryProvider(memoryId -> 
    MessageWindowChatMemory.withMaxMessages(10)
)

工作原理

用户调用 chat(memoryId=1, message="...")
       ↓
LangChain4j 检查缓存:memoryId=1 是否存在?
       ↓
不存在 → 调用 chatMemoryProvider.create(memoryId=1)
       ↓
创建新的 ChatMemory 实例
       ↓
缓存该实例(key=memoryId)
       ↓
后续调用直接复用缓存实例

关键点

  • ✅ 懒加载:首次访问时创建
  • ✅ 自动缓存:相同 memoryId 复用
  • ✅ 线程安全:内部使用 ConcurrentHashMap

2.3 实战案例:Web 聊天系统(Spring Boot)

(1)需求

构建支持多用户的网页聊天系统,要求:

  • 每个用户登录后看到自己的对话历史
  • 不同用户记忆严格隔离
  • 支持并发访问

(2)Controller 层

@RestController
@RequestMapping("/api/chat")
public class ChatController {

    @Autowired
    private CustomerServiceAssistant assistant;

    @Autowired
    private UserService userService;

    /**
     * 发送消息并获取 AI 回复
     */
    @PostMapping("/send")
    public ResponseEntity<String> sendMessage(
            @RequestHeader("Authorization") String token,
            @RequestBody ChatRequest request) {
        
        // 从 Token 中获取用户 ID
        Long userId = userService.getUserIdFromToken(token);
        
        // 调用 AI Service(自动使用 userId 作为 memoryId)
        String reply = assistant.chat(userId, request.getMessage());
        
        return ResponseEntity.ok(reply);
    }
}

(3)AI Service 接口

@AiService
public interface CustomerServiceAssistant {

    @SystemMessage("你是电商平台的智能客服助手")
    String chat(@MemoryId Long userId, @UserMessage String message);
}

(4)前端调用

async function sendMessage(message) {
    const response = await fetch('/api/chat/send', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': localStorage.getItem('token')
        },
        body: JSON.stringify({ message })
    });
    
    const reply = await response.text();
    displayMessage('AI', reply);
}

效果

  • 用户 A 登录后,只能看到自己的对话历史
  • 用户 B 登录后,看到的是完全不同的对话历史
  • 两个用户同时聊天,互不干扰

三、持久化记忆:重启不丢失

3.1 问题

内存中的 ChatMemory 在程序重启后会丢失所有对话历史

第一次运行:
用户:我叫张三
AI:你好,张三!

重启程序...

第二次运行:
用户:我叫什么名字?
AI:抱歉,我不知道。  ← ❌ 记忆丢失

3.2 解决方案:ChatMemoryStore 接口

LangChain4j 提供 ChatMemoryStore 接口,支持自定义持久化存储:

public interface ChatMemoryStore {
    
    // 获取消息
    List<ChatMessage> getMessages(Object memoryId);
    
    // 更新消息
    void updateMessages(Object memoryId, List<ChatMessage> messages);
    
    // 删除消息
    void deleteMessages(Object memoryId);
}

实现方案

存储类型 适用场景 优点 缺点
内存 开发调试 快速、简单 重启丢失
MapDB 小规模应用 零配置、文件存储 并发性能一般
SQLite 中小规模 轻量级、易部署 高并发受限
MySQL 中大规模 高性能、可扩展 需要数据库运维
Redis 高并发场景 极速、支持 TTL 成本高、需运维

3.3 MapDB 持久化(文件存储)

public class ServiceWithPersistentMemoryForEachUserExample {

    interface Assistant {
        String chat(@MemoryId int memoryId, @UserMessage String userMessage);
    }

    public static void main(String[] args) {

        // 创建持久化存储
        PersistentChatMemoryStore store = new PersistentChatMemoryStore();

        // 创建记忆提供者
        ChatMemoryProvider chatMemoryProvider = memoryId -> 
            MessageWindowChatMemory.builder()
                .id(memoryId)
                .maxMessages(10)
                .chatMemoryStore(store)  // 使用持久化存储
                .build();

        ChatModel model = OpenAiChatModel.builder()
                .baseUrl("http://langchain4j.dev/demo/openai/v1")
                .modelName("gpt-4o-mini")
                .apiKey("demo")
                .build();

        Assistant assistant = AiServices.builder(Assistant.class)
                .chatModel(model)
                .chatMemoryProvider(chatMemoryProvider)
                .build();

        // 第一次运行:保存对话
        System.out.println(assistant.chat(1, "Hello, my name is Klaus"));
        System.out.println(assistant.chat(2, "Hi, my name is Francine"));

        // 重启程序后,注释掉上面两行,取消注释下面两行
        // System.out.println(assistant.chat(1, "What is my name?"));
        // System.out.println(assistant.chat(2, "What is my name?"));
        // 输出:Your name is Klaus. / Your name is Francine.
    }

    /**
     * 持久化聊天记忆存储实现(使用 MapDB)
     */
    static class PersistentChatMemoryStore implements ChatMemoryStore {

        private final DB db = DBMaker.fileDB("multi-user-chat-memory.db")
                .transactionEnable()
                .make();
        
        private final Map<Integer, String> map = db.hashMap("messages", INTEGER, STRING)
                .createOrOpen();

        @Override
        public List<ChatMessage> getMessages(Object memoryId) {
            String json = map.get((int) memoryId);
            return messagesFromJson(json);
        }

        @Override
        public void updateMessages(Object memoryId, List<ChatMessage> messages) {
            String json = messagesToJson(messages);
            map.put((int) memoryId, json);
            db.commit();  // 提交事务
        }

        @Override
        public void deleteMessages(Object memoryId) {
            map.remove((int) memoryId);
            db.commit();
        }
    }
}

工作原理

保存消息:
ChatMessage 列表 → JSON 序列化 → MapDB 存储 → 写入文件

读取消息:
从文件读取 → MapDB 查询 → JSON 反序列化 → ChatMessage 列表

优势

  • ✅ 零配置:无需安装数据库
  • ✅ 文件存储:便于备份和迁移
  • ✅ 事务支持:保证数据一致性
  • ✅ 适合小规模:几千用户以内

劣势

  • ❌ 并发性能一般
  • ❌ 不支持分布式
  • ❌ 文件大小随数据增长

3.4 MySQL 持久化(生产环境推荐)

(1)数据库表设计

CREATE TABLE chat_memory (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    memory_id VARCHAR(255) NOT NULL,  -- 用户 ID 或会话 ID
    message_index INT NOT NULL,        -- 消息索引
    message_type VARCHAR(50) NOT NULL, -- SYSTEM/USER/AI
    content TEXT NOT NULL,             -- 消息内容
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_memory_id (memory_id),
    UNIQUE KEY uk_memory_index (memory_id, message_index)
);

(2)JPA Entity

@Entity
@Table(name = "chat_memory")
@Data
public class ChatMemoryEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "memory_id", nullable = false)
    private String memoryId;

    @Column(name = "message_index", nullable = false)
    private Integer messageIndex;

    @Column(name = "message_type", nullable = false)
    private String messageType;

    @Column(name = "content", columnDefinition = "LONGTEXT")
    private String content;

    @Column(name = "created_at")
    private LocalDateTime createdAt;
}

(3)Repository

@Repository
public interface ChatMemoryRepository extends JpaRepository<ChatMemoryEntity, Long> {
    
    List<ChatMemoryEntity> findByMemoryIdOrderByMessageIndexAsc(String memoryId);
    
    void deleteByMemoryId(String memoryId);
    
    int countByMemoryId(String memoryId);
}

(4)自定义 ChatMemoryStore

@Component
public class MySqlChatMemoryStore implements ChatMemoryStore {

    @Autowired
    private ChatMemoryRepository repository;

    @Override
    public List<ChatMessage> getMessages(Object memoryId) {
        String memId = (String) memoryId;
        
        return repository.findByMemoryIdOrderByMessageIndexAsc(memId)
            .stream()
            .map(this::convertToChatMessage)
            .collect(Collectors.toList());
    }

    @Override
    public void updateMessages(Object memoryId, List<ChatMessage> messages) {
        String memId = (String) memoryId;
        
        // 删除旧消息
        repository.deleteByMemoryId(memId);
        
        // 保存新消息
        for (int i = 0; i < messages.size(); i++) {
            ChatMessage message = messages.get(i);
            
            ChatMemoryEntity entity = new ChatMemoryEntity();
            entity.setMemoryId(memId);
            entity.setMessageIndex(i);
            entity.setMessageType(getMessageType(message));
            entity.setContent(extractContent(message));
            entity.setCreatedAt(LocalDateTime.now());
            
            repository.save(entity);
        }
    }

    @Override
    public void deleteMessages(Object memoryId) {
        repository.deleteByMemoryId((String) memoryId);
    }

    private ChatMessage convertToChatMessage(ChatMemoryEntity entity) {
        switch (entity.getMessageType()) {
            case "SYSTEM":
                return SystemMessage.from(entity.getContent());
            case "USER":
                return UserMessage.from(entity.getContent());
            case "AI":
                return AiMessage.from(entity.getContent());
            default:
                throw new IllegalArgumentException("未知消息类型:" + entity.getMessageType());
        }
    }

    private String getMessageType(ChatMessage message) {
        if (message instanceof SystemMessage) return "SYSTEM";
        if (message instanceof UserMessage) return "USER";
        if (message instanceof AiMessage) return "AI";
        throw new IllegalArgumentException("未知消息类型");
    }

    private String extractContent(ChatMessage message) {
        return message.text();
    }
}

(5)配置 Bean

@Configuration
public class LangChain4jConfig {

    @Autowired
    private MySqlChatMemoryStore memoryStore;

    @Bean
    public ChatMemoryProvider chatMemoryProvider() {
        return memoryId -> MessageWindowChatMemory.builder()
            .id(memoryId)
            .maxMessages(50)
            .chatMemoryStore(memoryStore)
            .build();
    }

    @Bean
    public ChatModel chatModel() {
        return OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4o-mini")
            .build();
    }
}

(6)AI Service

@AiService
public interface CustomerServiceAssistant {

    @SystemMessage("你是客服助手")
    String chat(@MemoryId String userId, @UserMessage String message);
}

效果

  • ✅ 支持百万级用户
  • ✅ 高并发访问
  • ✅ 数据持久化
  • ✅ 易于备份和恢复

3.5 Redis 持久化(高性能场景)

(1)依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

(2)application.properties

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=

(3)RedisChatMemoryStore

@Component
public class RedisChatMemoryStore implements ChatMemoryStore {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final String KEY_PREFIX = "chat:memory:";
    private static final long TTL_SECONDS = 30 * 24 * 3600;  // 30 天过期

    @Override
    public List<ChatMessage> getMessages(Object memoryId) {
        String key = KEY_PREFIX + memoryId;
        String json = redisTemplate.opsForValue().get(key);
        
        if (json == null) {
            return Collections.emptyList();
        }
        
        return messagesFromJson(json);
    }

    @Override
    public void updateMessages(Object memoryId, List<ChatMessage> messages) {
        String key = KEY_PREFIX + memoryId;
        String json = messagesToJson(messages);
        
        // 保存并设置过期时间
        redisTemplate.opsForValue().set(key, json, TTL_SECONDS, TimeUnit.SECONDS);
    }

    @Override
    public void deleteMessages(Object memoryId) {
        String key = KEY_PREFIX + memoryId;
        redisTemplate.delete(key);
    }
}

优势

  • ✅ 极速读写(毫秒级)
  • ✅ 自动过期(TTL)
  • ✅ 支持分布式
  • ✅ 高并发友好

劣势

  • ❌ 成本较高
  • ❌ 需要运维
  • ❌ 数据可能丢失(需配置持久化)

四、会话 ID 生成策略

4.1 常见策略对比

策略 说明 优点 缺点
数据库用户 ID 使用主键 ID 唯一、稳定 需要登录
UUID 随机生成 无需登录 无法跨设备同步
Session ID Servlet Session 简单易用 服务器重启丢失
邮箱/手机号 业务标识 用户友好 可能变更
设备指纹 浏览器特征 无需登录 不准确

4.2 推荐方案

(1)已登录用户

// 使用数据库用户 ID
Long userId = securityContext.getUserId();
String reply = assistant.chat(userId, message);

(2)未登录用户

// 生成 UUID 作为临时会话 ID
String sessionId = UUID.randomUUID().toString();
session.setAttribute("chatSessionId", sessionId);

String reply = assistant.chat(sessionId, message);

(3)混合方案

@GetMapping("/chat")
public String chat(HttpServletRequest request, @RequestParam String message) {
    
    // 优先使用用户 ID
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    
    Object memoryId;
    if (auth != null && auth.isAuthenticated()) {
        // 已登录:使用用户 ID
        memoryId = ((UserDetails) auth.getPrincipal()).getId();
    } else {
        // 未登录:使用 Session ID
        HttpSession session = request.getSession(true);
        memoryId = session.getId();
    }
    
    return assistant.chat(memoryId, message);
}

效果

  • 已登录用户:对话历史永久保存,跨设备同步
  • 未登录用户:临时会话,关闭浏览器后失效

五、数据清理策略

5.1 为什么需要清理?

  • 💾 存储空间:避免数据库无限增长
  • 🔒 隐私保护:删除过期敏感数据
  • 性能优化:减少查询负担

5.2 清理策略

(1)基于时间的清理(TTL)

Redis 自动过期

redisTemplate.opsForValue().set(key, json, 30, TimeUnit.DAYS);

MySQL 定时任务

@Component
public class ChatMemoryCleanupTask {

    @Autowired
    private ChatMemoryRepository repository;

    /**
     * 每天凌晨 2 点清理 30 天未活跃的会话
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void cleanup() {
        
        LocalDateTime cutoffTime = LocalDateTime.now().minusDays(30);
        
        // 删除 30 天前的记录
        int deletedCount = repository.deleteByCreatedAtBefore(cutoffTime);
        
        logger.info("清理了 {} 条过期会话记录", deletedCount);
    }
}

(2)基于大小的清理

@Service
public class MemorySizeLimitService {

    @Autowired
    private ChatMemoryRepository repository;

    private static final int MAX_MESSAGES_PER_USER = 100;

    public void enforceLimit(String memoryId) {
        
        int count = repository.countByMemoryId(memoryId);
        
        if (count > MAX_MESSAGES_PER_USER) {
            // 删除最早的消息,保留最近 100 条
            List<ChatMemoryEntity> oldMessages = repository.findOldMessages(memoryId, MAX_MESSAGES_PER_USER);
            repository.deleteAll(oldMessages);
            
            logger.info("用户 {} 超出限制,清理了 {} 条旧消息", memoryId, oldMessages.size());
        }
    }
}

(3)基于活跃度的清理

/**
 * 清理 90 天未活跃的会话
 */
@Scheduled(cron = "0 0 3 * * ?")
public void cleanupInactiveSessions() {
    
    LocalDateTime cutoffTime = LocalDateTime.now().minusDays(90);
    
    // 查询 90 天未更新的会话 ID
    List<String> inactiveIds = repository.findInactiveMemoryIds(cutoffTime);
    
    // 批量删除
    for (String memoryId : inactiveIds) {
        repository.deleteByMemoryId(memoryId);
    }
    
    logger.info("清理了 {} 个非活跃会话", inactiveIds.size());
}

六、常见问题与避坑指南

6.1 记忆泄漏(串号)

现象

用户 A 看到用户 B 的对话历史

原因

  • memoryId 重复
  • 缓存未正确隔离

解决方案

// ✅ 确保 memoryId 唯一
String memoryId = userId + ":" + sessionId;  // 组合 ID

// ✅ 使用线程安全的 ChatMemoryProvider
.chatMemoryProvider(memoryId -> 
    MessageWindowChatMemory.withMaxMessages(10)
)

6.2 并发写入冲突

现象

两个请求同时更新同一用户的记忆,数据丢失

解决方案

方式 1:数据库乐观锁

@Entity
public class ChatMemoryEntity {
    
    @Version
    private Long version;  // 版本号
    
    // ... 其他字段
}

方式 2:Redis 原子操作

// 使用 Lua 脚本保证原子性
String luaScript = """
    local key = KEYS[1]
    local value = ARGV[1]
    redis.call('SET', key, value)
    redis.call('EXPIRE', key, ARGV[2])
    """;

redisTemplate.execute(new DefaultRedisScript<>(luaScript), 
    Collections.singletonList(key), 
    json, 
    String.valueOf(TTL_SECONDS)
);

6.3 内存溢出

现象

OutOfMemoryError: Java heap space

原因

  • 缓存了大量 ChatMemory 实例
  • 未设置上限

解决方案

// ✅ 使用 LRU 缓存,限制最大容量
private final Cache<Object, ChatMemory> memoryCache = Caffeine.newBuilder()
    .maximumSize(10_000)  // 最多缓存 1 万个用户
    .expireAfterAccess(1, TimeUnit.HOURS)  // 1 小时未访问则移除
    .build();

.chatMemoryProvider(memoryId -> 
    memoryCache.get(memoryId, id -> 
        MessageWindowChatMemory.withMaxMessages(50)
    )
)

七、最佳实践

7.1 memoryId 设计规范

推荐

// 已登录用户:使用用户 ID
@MemoryId Long userId

// 未登录用户:使用 Session ID
@MemoryId String sessionId

// 混合场景:组合 ID
@MemoryId String memoryId = "user:" + userId + ":session:" + sessionId

避免

// ❌ 使用可变对象
@MemoryId User user  // hashCode 可能变化

// ❌ 使用敏感信息
@MemoryId String phoneNumber  // 隐私泄露风险

7.2 存储选型建议

用户规模 推荐方案 原因
< 1000 MapDB/SQLite 简单、零配置
1000 - 10万 MySQL 成熟、可靠
> 10万 MySQL + Redis 高性能、可扩展
> 100万 Redis Cluster + MySQL 分布式、高可用

7.3 监控与告警

@Component
public class ChatMemoryMetrics {

    @Autowired
    private ChatMemoryRepository repository;

    @Scheduled(fixedRate = 60_000)  // 每分钟统计
    public void collectMetrics() {
        
        // 总会话数
        long totalSessions = repository.countDistinctMemoryIds();
        
        // 总消息数
        long totalMessages = repository.count();
        
        // 平均每个会话的消息数
        double avgMessages = totalMessages / (double) totalSessions;
        
        // 记录指标
        Metrics.gauge("chat.memory.sessions", totalSessions);
        Metrics.gauge("chat.memory.messages", totalMessages);
        Metrics.gauge("chat.memory.avg_messages_per_session", avgMessages);
        
        // 告警
        if (totalMessages > 10_000_000) {
            alertService.sendAlert("聊天消息数超过 1000 万");
        }
    }
}

结语

通过本文的学习,你已经掌握了企业级多用户对话系统的核心技术。从 @MemoryId 实现用户隔离,到 ChatMemoryProvider 动态管理记忆实例,再到 MapDB、MySQL、Redis 等多种持久化方案,这些技术能支撑从几百到上千万用户的规模化应用。记住,好的记忆系统设计需要考虑三个维度:隔离性(用户间互不干扰)、持久性(重启不丢失)、可扩展性(支持水平扩展)。在实际项目中,建议从小规模起步(MapDB/SQLite),随着用户增长逐步迁移到 MySQL + Redis 架构,同时建立完善的监控和清理机制,确保系统长期稳定运行。


在这里插入图片描述

🎯🔖更多专栏系列文章:AI大模型提示工程完全指南AI大模型探索之路(零基础入门)AI大模型预训练微调进阶AI大模型开源精选实践AI大模型Spring AI开发实战🔥🔥🔥 其他专栏可以查看博客主页

🔔 关于作者:资深程序老猿,10年+架构经验,现专注 AIGC 探索与实践。
👍 若文章对你有所触动,恳请点赞 ⭐ 关注 ⭐ 收藏!AI 浪潮已至,愿与你同行。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐