Rust与Redis数据库开发实战:构建高性能会话管理系统

Rust与Redis数据库开发实战:构建高性能会话管理系统

Rust与Redis数据库开发实战:构建高性能会话管理系统

在这里插入图片描述

一、引言

💡Redis是一款高性能的内存数据库,它支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等,具有读写速度快、内存占用少、跨平台等特点,非常适合开发缓存、消息队列、会话管理、实时数据分析等应用。

Rust语言以其内存安全、高性能和良好的工具链支持,成为开发Redis应用的理想选择。Rust生态系统中提供了多个优秀的Redis库,其中redis-rs是最成熟、最流行的一个。redis-rs提供了安全、易用的API,支持Redis的全部功能,包括事务处理、管道操作、发布订阅等。

二、开发环境搭建

2.1 安装Redis

Redis通常已经预装在大多数操作系统中,你可以通过以下命令检查是否安装:

# 检查Redis版本 redis-cli --version

如果没有安装,可以通过以下命令安装:

macOS
# 使用Homebrew安装 brew install redis # 启动Redis服务 brew services start redis 
Ubuntu/Debian
# 使用apt-get安装sudoapt-get update sudoapt-getinstall-y redis-server # 启动Redis服务sudo systemctl start redis-server 
Windows

下载Redis官方预编译二进制文件:https://github.com/microsoftarchive/redis/releases,解压后将redis-cli.exeredis-server.exe添加到系统路径中。

2.2 创建Rust项目

使用Cargo创建一个新的Rust项目:

# 创建项目cargo new rust-redis-session cd rust-redis-session # 查看项目结构ls-la

2.3 安装redis-rs依赖

Cargo.toml中添加redis-rs依赖:

[package] name = "rust-redis-session" version = "0.1.0" edition = "2021" [dependencies] redis = { version = "0.25", features = ["tokio-comp"] } tokio = { version = "1.0", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "1.0", features = ["v4"] } chrono = { version = "0.4", features = ["serde"] } thiserror = "1.0" clap = { version = "4.5", features = ["derive"] } 

依赖说明:

  • redis-rs:Redis的Rust绑定,支持异步操作。
  • tokio:Rust的异步运行时。
  • serde:数据序列化/反序列化库。
  • serde_json:JSON数据序列化/反序列化库。
  • uuid:UUID生成库。
  • chrono:日期和时间处理库。
  • thiserror:自定义错误类型库。
  • clap:命令行参数解析库。

三、Redis基本操作

3.1 连接Redis

使用redis-rs连接Redis:

// src/main.rsuseredis::RedisError;usestd::env;asyncfnconnect_redis()->Result<redis::Client,RedisError>{let redis_url =env::var("REDIS_URL").unwrap_or_else(|_|"redis://127.0.0.1:6379".to_string());let client =redis::Client::open(redis_url)?;println!("Successfully connected to Redis");Ok(client)}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let client =connect_redis().await?;Ok(())}

3.2 字符串操作

使用字符串操作存储和获取数据:

// src/main.rsuseredis::AsyncCommands;useredis::RedisError;asyncfnstring_example(client:&redis::Client)->Result<(),RedisError>{letmut con = client.get_async_connection().await?;// 设置值 con.set("username","admin").await?;println!("Successfully set username: admin");// 获取值let username:String= con.get("username").await?;println!("Successfully got username: {}", username);// 设置值并指定过期时间 con.set_ex("token","abc123",3600).await?;println!("Successfully set token: abc123 (expires in 3600 seconds)");// 获取值并检查过期时间let token:Option<String>= con.get("token").await?;ifletSome(token)= token {println!("Successfully got token: {}", token);}else{println!("Token not found");}Ok(())}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let client =connect_redis().await?;string_example(&client).await?;Ok(())}

3.3 哈希操作

使用哈希操作存储和获取数据:

// src/main.rsuseredis::AsyncCommands;useredis::RedisError;asyncfnhash_example(client:&redis::Client)->Result<(),RedisError>{letmut con = client.get_async_connection().await?;// 设置哈希值 con.hset("user:1","name","admin").await?; con.hset("user:1","email","[email protected]").await?; con.hset("user:1","password","password123").await?;println!("Successfully set user:1");// 获取哈希值let name:String= con.hget("user:1","name").await?;let email:String= con.hget("user:1","email").await?;let password:String= con.hget("user:1","password").await?;println!("Successfully got user:1");println!("Name: {}", name);println!("Email: {}", email);println!("Password: {}", password);// 获取所有哈希字段和值let user:Vec<(String,String)>= con.hgetall("user:1").await?;println!("Successfully got user:1 fields and values: {:?}", user);// 删除哈希字段 con.hdel("user:1","password").await?;println!("Successfully deleted user:1 password");Ok(())}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let client =connect_redis().await?;hash_example(&client).await?;Ok(())}

3.4 列表操作

使用列表操作存储和获取数据:

// src/main.rsuseredis::AsyncCommands;useredis::RedisError;asyncfnlist_example(client:&redis::Client)->Result<(),RedisError>{letmut con = client.get_async_connection().await?;// 向列表添加元素 con.lpush("tasks","Learn Rust").await?; con.lpush("tasks","Learn Redis").await?; con.lpush("tasks","Build Project").await?;println!("Successfully added tasks to list");// 获取列表长度let length:i64= con.llen("tasks").await?;println!("Tasks list length: {}", length);// 获取列表元素let tasks:Vec<String>= con.lrange("tasks",0,-1).await?;println!("Tasks list: {:?}", tasks);// 从列表左侧弹出元素let task:String= con.lpop("tasks").await?;println!("Successfully popped task from left: {}", task);// 从列表右侧弹出元素let task:String= con.rpop("tasks").await?;println!("Successfully popped task from right: {}", task);Ok(())}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let client =connect_redis().await?;list_example(&client).await?;Ok(())}

3.5 集合操作

使用集合操作存储和获取数据:

// src/main.rsuseredis::AsyncCommands;useredis::RedisError;asyncfnset_example(client:&redis::Client)->Result<(),RedisError>{letmut con = client.get_async_connection().await?;// 向集合添加元素 con.sadd("tags","Rust").await?; con.sadd("tags","Redis").await?; con.sadd("tags","Web").await?;println!("Successfully added tags to set");// 获取集合元素let tags:Vec<String>= con.smembers("tags").await?;println!("Tags set: {:?}", tags);// 检查元素是否存在let exists:bool= con.sismember("tags","Rust").await?;println!("Tag Rust exists: {}", exists);// 删除元素 con.srem("tags","Web").await?;println!("Successfully removed tag Web from set");Ok(())}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let client =connect_redis().await?;set_example(&client).await?;Ok(())}

3.6 有序集合操作

使用有序集合操作存储和获取数据:

// src/main.rsuseredis::AsyncCommands;useredis::RedisError;asyncfnzset_example(client:&redis::Client)->Result<(),RedisError>{letmut con = client.get_async_connection().await?;// 向有序集合添加元素 con.zadd("scores","user1",90).await?; con.zadd("scores","user2",85).await?; con.zadd("scores","user3",95).await?;println!("Successfully added scores to zset");// 获取有序集合元素let scores:Vec<(String,i32)>= con.zrange_withscores("scores",0,-1).await?;println!("Scores zset: {:?}", scores);// 获取有序集合元素并按分数降序排序let scores_desc:Vec<(String,i32)>= con.zrevrange_withscores("scores",0,-1).await?;println!("Scores zset (desc): {:?}", scores_desc);// 获取元素的分数let score:i32= con.zscore("scores","user1").await?;println!("User1 score: {}", score);Ok(())}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let client =connect_redis().await?;zset_example(&client).await?;Ok(())}

四、实战项目:高性能会话管理系统

4.1 项目概述

开发一个高性能的会话管理系统,支持以下功能:

  • 用户登录:验证用户名和密码
  • 会话创建:创建新的会话
  • 会话验证:验证会话的有效性
  • 会话过期:自动清理过期的会话
  • 会话统计:统计会话数量

4.2 数据结构设计

使用Redis的字符串、哈希、集合等数据结构存储会话数据:

  • 会话ID:使用UUID生成
  • 会话数据:存储在哈希中,包括用户ID、用户名、过期时间等
  • 会话集合:存储所有有效的会话ID
  • 用户会话映射:存储用户ID到会话ID的映射

4.3 代码实现

4.3.1 定义会话结构体
// src/session.rsusechrono::{DateTime,Utc};useserde::{Deserialize,Serialize};useuuid::Uuid;#[derive(Debug, Clone, Serialize, Deserialize)]pubstructSession{pub id:String,pub user_id:String,pub username:String,pub created_at:DateTime<Utc>,pub expires_at:DateTime<Utc>,}implSession{pubfnnew(user_id:String, username:String, expires_in:i64)->Self{let id =Uuid::new_v4().to_string();let created_at =Utc::now();let expires_at = created_at +chrono::Duration::seconds(expires_in);Session{ id, user_id, username, created_at, expires_at,}}pubfnis_expired(&self)->bool{Utc::now()>self.expires_at }}
4.3.2 定义会话管理结构体
// src/session.rsuseredis::AsyncCommands;useredis::RedisError;usestd::collections::HashMap;usecrate::session::Session;#[derive(Debug)]pubstructSessionManager{ client:redis::Client, prefix:String, default_expires_in:i64,}implSessionManager{pubfnnew(client:redis::Client, prefix:String, default_expires_in:i64)->Self{SessionManager{ client, prefix, default_expires_in,}}pubasyncfncreate_session(&self, user_id:String, username:String)->Result<Session,RedisError>{let session =Session::new(user_id, username,self.default_expires_in);letmut con =self.client.get_async_connection().await?;// 存储会话数据let session_key =format!("{}:{}",self.prefix, session.id); con.hset(&session_key,"user_id",&session.user_id).await?; con.hset(&session_key,"username",&session.username).await?; con.hset(&session_key,"created_at",&session.created_at.to_rfc3339()).await?; con.hset(&session_key,"expires_at",&session.expires_at.to_rfc3339()).await?; con.expire(&session_key,self.default_expires_in).await?;println!("Successfully created session: {}", session.id);// 添加到会话集合let sessions_key =format!("{}:sessions",self.prefix); con.sadd(&sessions_key,&session.id).await?;println!("Successfully added session to sessions set: {}", session.id);// 添加到用户会话映射let user_sessions_key =format!("{}:user:{}",self.prefix, session.user_id); con.sadd(&user_sessions_key,&session.id).await?;println!("Successfully added session to user sessions: {}", session.id);Ok(session)}pubasyncfnget_session(&self, session_id:&str)->Result<Option<Session>,RedisError>{letmut con =self.client.get_async_connection().await?;let session_key =format!("{}:{}",self.prefix, session_id);// 获取会话数据let session_data:Option<HashMap<String,String>>= con.hgetall(&session_key).await?;ifletSome(session_data)= session_data {let session =Session{ id: session_id.to_string(), user_id: session_data.get("user_id").unwrap_or(&"".to_string()).to_string(), username: session_data.get("username").unwrap_or(&"".to_string()).to_string(), created_at:DateTime::parse_from_rfc3339(session_data.get("created_at").unwrap_or(&"".to_string())).unwrap().with_timezone(&Utc), expires_at:DateTime::parse_from_rfc3339(session_data.get("expires_at").unwrap_or(&"".to_string())).unwrap().with_timezone(&Utc),};// 检查会话是否过期if session.is_expired(){self.delete_session(session_id).await?;Ok(None)}else{Ok(Some(session))}}else{Ok(None)}}pubasyncfndelete_session(&self, session_id:&str)->Result<(),RedisError>{letmut con =self.client.get_async_connection().await?;let session_key =format!("{}:{}",self.prefix, session_id);// 获取会话数据以删除用户会话映射let session_data:Option<HashMap<String,String>>= con.hgetall(&session_key).await?;ifletSome(session_data)= session_data {let user_id = session_data.get("user_id").unwrap_or(&"".to_string()).to_string();let user_sessions_key =format!("{}:user:{}",self.prefix, user_id); con.srem(&user_sessions_key, session_id).await?;println!("Successfully removed session from user sessions: {}", session_id);}// 删除会话数据 con.del(&session_key).await?;println!("Successfully deleted session data: {}", session_id);// 从会话集合中删除let sessions_key =format!("{}:sessions",self.prefix); con.srem(&sessions_key, session_id).await?;println!("Successfully removed session from sessions set: {}", session_id);Ok(())}pubasyncfnget_user_sessions(&self, user_id:&str)->Result<Vec<Session>,RedisError>{letmut con =self.client.get_async_connection().await?;let user_sessions_key =format!("{}:user:{}",self.prefix, user_id);// 获取用户的所有会话IDlet session_ids:Vec<String>= con.smembers(&user_sessions_key).await?;letmut sessions =Vec::new();// 获取每个会话的数据for session_id in session_ids {ifletSome(session)=self.get_session(&session_id).await?{ sessions.push(session);}}Ok(sessions)}pubasyncfnclean_expired_sessions(&self)->Result<(),RedisError>{letmut con =self.client.get_async_connection().await?;let sessions_key =format!("{}:sessions",self.prefix);// 获取所有会话IDlet session_ids:Vec<String>= con.smembers(&sessions_key).await?;for session_id in session_ids {ifletSome(session)=self.get_session(&session_id).await?{if session.is_expired(){self.delete_session(&session_id).await?;}}}println!("Successfully cleaned expired sessions");Ok(())}}
4.3.3 定义用户认证模块
// src/auth.rsuseserde::{Deserialize,Serialize};#[derive(Debug, Clone, Serialize, Deserialize)]pubstructUser{pub id:String,pub username:String,pub password:String,}implUser{pubfnnew(id:String, username:String, password:String)->Self{User{ id, username, password }}}#[derive(Debug, Clone)]pubstructAuthManager{ users:Vec<User>,}implAuthManager{pubfnnew(users:Vec<User>)->Self{AuthManager{ users }}pubfnauthenticate(&self, username:&str, password:&str)->Option<User>{self.users.iter().find(|user| user.username == username && user.password == password).cloned()}}
4.3.4 定义命令行界面
// src/cli.rsuseclap::Parser;useserde::{Deserialize,Serialize};#[derive(Parser, Debug)]#[command(name = "rust-redis-session")]#[command(about = "A high-performance session management system written in Rust")]structArgs{#[command(subcommand)] command:Commands,}#[derive(clap::Subcommand, Debug)]enumCommands{#[command(about = "User login")]Login{#[arg(short, long, help = "Username")] username:String,#[arg(short, long, help = "Password")] password:String,},#[command(about = "Get session by ID")]Get{#[arg(short, long, help = "Session ID")] session_id:String,},#[command(about = "Delete session by ID")]Delete{#[arg(short, long, help = "Session ID")] session_id:String,},#[command(about = "Get user sessions")]User{#[arg(short, long, help = "User ID")] user_id:String,},#[command(about = "Clean expired sessions")]Clean,}
4.3.5 定义主函数
// src/main.rsuseredis::RedisError;usestd::env;usecrate::auth::AuthManager;usecrate::auth::User;usecrate::cli::Args;usecrate::session::SessionManager;asyncfnconnect_redis()->Result<redis::Client,RedisError>{let redis_url =env::var("REDIS_URL").unwrap_or_else(|_|"redis://127.0.0.1:6379".to_string());let client =redis::Client::open(redis_url)?;println!("Successfully connected to Redis");Ok(client)}asyncfnlogin(session_manager:&SessionManager, auth_manager:&AuthManager, username:&str, password:&str)->Result<(),RedisError>{match auth_manager.authenticate(username, password){Some(user)=>{let session = session_manager.create_session(user.id, user.username).await?;println!("Successfully logged in");println!("Session ID: {}", session.id);println!("Expires at: {}", session.expires_at);}None=>{println!("Invalid username or password");}}Ok(())}asyncfnget_session(session_manager:&SessionManager, session_id:&str)->Result<(),RedisError>{match session_manager.get_session(session_id).await?{Some(session)=>{println!("Successfully got session: {}", session.id);println!("User ID: {}", session.user_id);println!("Username: {}", session.username);println!("Created at: {}", session.created_at);println!("Expires at: {}", session.expires_at);}None=>{println!("Session not found or expired");}}Ok(())}asyncfndelete_session(session_manager:&SessionManager, session_id:&str)->Result<(),RedisError>{ session_manager.delete_session(session_id).await?;println!("Successfully deleted session: {}", session_id);Ok(())}asyncfnget_user_sessions(session_manager:&SessionManager, user_id:&str)->Result<(),RedisError>{let sessions = session_manager.get_user_sessions(user_id).await?;println!("Successfully got user sessions: {}", user_id);for session in sessions {println!("Session ID: {}", session.id);println!("Created at: {}", session.created_at);println!("Expires at: {}", session.expires_at);println!("---");}Ok(())}asyncfnclean_expired_sessions(session_manager:&SessionManager)->Result<(),RedisError>{ session_manager.clean_expired_sessions().await?;Ok(())}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let args =Args::parse();let client =connect_redis().await?;let session_manager =SessionManager::new(client,"session".to_string(),3600);let users =vec![User::new("1","admin","password123"),User::new("2","user1","password456"),User::new("3","user2","password789"),];let auth_manager =AuthManager::new(users);match args.command {Commands::Login{ username, password }=>{login(&session_manager,&auth_manager,&username,&password).await?;}Commands::Get{ session_id }=>{get_session(&session_manager,&session_id).await?;}Commands::Delete{ session_id }=>{delete_session(&session_manager,&session_id).await?;}Commands::User{ user_id }=>{get_user_sessions(&session_manager,&user_id).await?;}Commands::Clean=>{clean_expired_sessions(&session_manager).await?;}}Ok(())}

4.4 测试项目

运行会话管理系统:

# 编译项目cargo build # 启动Redis服务器(如果未启动) redis-server # 用户登录cargo run -- login --username admin --password password123 # 获取会话cargo run -- get --session-id <session-id># 删除会话cargo run -- delete --session-id <session-id># 获取用户会话cargo run -- user --user-id 1# 清理过期会话cargo run -- clean 

五、性能优化

5.1 使用连接池

使用连接池管理Redis连接:

// src/connection_pool.rsuseredis::RedisError;use r2d2;user2d2_redis::RedisConnectionManager;asyncfncreate_connection_pool()->Result<r2d2::Pool<RedisConnectionManager>,RedisError>{let redis_url =env::var("REDIS_URL").unwrap_or_else(|_|"redis://127.0.0.1:6379".to_string());let manager =RedisConnectionManager::new(redis_url)?;let pool =r2d2::Pool::builder().max_size(10).build(manager)?;println!("Successfully created Redis connection pool");Ok(pool)}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let pool =create_connection_pool().await?;Ok(())}

5.2 使用批量操作

使用批量操作提升性能:

// src/session.rsuseredis::AsyncCommands;useredis::RedisError;usestd::collections::HashMap;implSessionManager{pubasyncfncreate_sessions(&self, users:Vec<(String,String)>)->Result<Vec<Session>,RedisError>{letmut con =self.client.get_async_connection().await?;letmut sessions =Vec::new();for(user_id, username)in users {let session =Session::new(user_id, username,self.default_expires_in);let session_key =format!("{}:{}",self.prefix, session.id); con.hset(&session_key,"user_id",&session.user_id).await?; con.hset(&session_key,"username",&session.username).await?; con.hset(&session_key,"created_at",&session.created_at.to_rfc3339()).await?; con.hset(&session_key,"expires_at",&session.expires_at.to_rfc3339()).await?; con.expire(&session_key,self.default_expires_in).await?;let sessions_key =format!("{}:sessions",self.prefix); con.sadd(&sessions_key,&session.id).await?;let user_sessions_key =format!("{}:user:{}",self.prefix, session.user_id); con.sadd(&user_sessions_key,&session.id).await?; sessions.push(session);}Ok(sessions)}}

5.3 使用管道操作

使用管道操作提升性能:

// src/session.rsuseredis::pipe;useredis::RedisError;implSessionManager{pubasyncfncreate_sessions_pipeline(&self, users:Vec<(String,String)>)->Result<Vec<Session>,RedisError>{letmut con =self.client.get_async_connection().await?;letmut pipe =pipe();letmut sessions =Vec::new();for(user_id, username)in users {let session =Session::new(user_id, username,self.default_expires_in);let session_key =format!("{}:{}",self.prefix, session.id);let sessions_key =format!("{}:sessions",self.prefix);let user_sessions_key =format!("{}:user:{}",self.prefix, session.user_id); pipe .hset(&session_key,"user_id",&session.user_id).ignore().hset(&session_key,"username",&session.username).ignore().hset(&session_key,"created_at",&session.created_at.to_rfc3339()).ignore().hset(&session_key,"expires_at",&session.expires_at.to_rfc3339()).ignore().expire(&session_key,self.default_expires_in).ignore().sadd(&sessions_key,&session.id).ignore().sadd(&user_sessions_key,&session.id).ignore(); sessions.push(session);} pipe.query_async(&mut con).await?;Ok(sessions)}}

5.4 优化缓存策略

使用缓存策略优化性能:

// src/cache.rsuseredis::AsyncCommands;useredis::RedisError;usestd::collections::HashMap;asyncfnoptimize_cache(client:&redis::Client)->Result<(),RedisError>{letmut con = client.get_async_connection().await?;// 使用set命令代替hset命令 con.set("user:1:name","admin").await?; con.set("user:1:email","[email protected]").await?;println!("Successfully set user data using set commands");// 使用get命令代替hget命令let name:String= con.get("user:1:name").await?;let email:String= con.get("user:1:email").await?;println!("Successfully got user data using get commands: name={}, email={}", name, email);Ok(())}#[tokio::main]asyncfnmain()->Result<(),RedisError>{let client =connect_redis().await?;optimize_cache(&client).await?;Ok(())}

六、总结

6.1 技术栈

  • Rust:开发语言
  • redis-rs:Redis的Rust绑定,支持异步操作
  • tokio:Rust的异步运行时
  • serde:数据序列化/反序列化库
  • uuid:UUID生成库
  • chrono:日期和时间处理库
  • thiserror:自定义错误类型库
  • clap:命令行参数解析库

6.2 核心功能

  • 用户登录:验证用户名和密码
  • 会话创建:创建新的会话
  • 会话验证:验证会话的有效性
  • 会话过期:自动清理过期的会话
  • 会话统计:统计会话数量

6.3 未来改进方向

  • 添加会话刷新功能:在会话即将过期时自动刷新会话的过期时间
  • 添加会话统计功能:统计会话的创建时间、过期时间、访问频率等
  • 添加会话限制功能:限制用户的会话数量
  • 添加会话加密功能:对会话数据进行加密存储
  • 添加会话备份功能:定期备份会话数据到磁盘

通过本章的学习,读者可以深入理解Rust与Redis数据库开发的工作原理和实现方法,并在实际项目中应用这些技术。同时,本章也介绍了如何优化Redis操作的性能,帮助读者构建高性能的应用。

Read more

Spring AI系列之RAG(检索增强生成)从原理到实战指南

Spring AI系列之RAG(检索增强生成)从原理到实战指南

Spring AI系列之RAG(检索增强生成)从原理到实战指南 在LLM(大语言模型)时代,如何让AI既拥有通用能力又具备专业知识?RAG技术给出了完美答案。本文将基于Spring AI生态,深入剖析RAG的核心原理、实现细节与优化策略。 一、为什么需要RAG? 在深入了解RAG之前,我们需要先认识传统LLM的局限性: 缺陷类型具体表现RAG解决方案知识截止模型知识有截止日期,无法获取最新信息实时检索外部知识库幻觉问题自信地生成看似合理但实际错误的内容基于检索到的真实信息生成上下文限制长文本处理能力有限只检索最相关的上下文片段领域专业度通用模型缺乏垂直领域深度知识外挂专业领域知识库 比喻理解:如果将LLM比作一个"高中毕业生",那么: * Fine-tuning(微调) = 让他花7年时间去医学院学习,然后成为医生 * RAG = 给他配备了一群专业主任医师作为顾问,遇到问题时先咨询专家再作答 二、RAG核心架构解析 2.1 整体工作流程 RAG的工作流程可以分为两大阶段:离线索引(Indexing) 和 在线检索生成(Retrieval & Gene

By Ne0inhk
一卡通核心交易平台的国产数据库实践解析:架构、迁移与高可用落地

一卡通核心交易平台的国产数据库实践解析:架构、迁移与高可用落地

文章目录 * 摘要 * 1. 业务与技术挑战拆解 * 2. 总体架构(从数据库边界看) * 3. 数据模型:以“不可变流水”为中心 * 3.1 流水表(交易事实表)建议 * 3.2 账户与余额:把“强一致”收敛到最小 * 4. 高可用与容灾:把“不可用窗口”工程化 * 4.1 同城高可用:主备切换与防脑裂 * 4.2 异地灾备:以“可恢复”为目标设计链路 * 5. 性能与稳定性:把瓶颈消灭在“写路径” * 5.1 连接治理:让资源可控 * 5.2 SQL治理:少做无谓计算

By Ne0inhk
【手写数据库内核miniToadb】第2天 与数据库交互的桥梁--SQL解绍

【手写数据库内核miniToadb】第2天 与数据库交互的桥梁--SQL解绍

专栏内容:手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者,在开源无限的公众号更新会更及时。 一、概述 上一节通过一个简单的C语言程序来模拟数据库的行为,从处理能力来看,也有创建表,插入、删除、更新、查询等操作,但是与大家认为的数据库差距很大。 关系型数据库的一个很明显的特点,就是有标准的操纵数据库的语言,它就是常用的SQL。我们来开发的数据库内核支持这一标准SQL,这样才能符合数据库的一个审美。 说到语言,就不得不做语言的解析了,类似于自然语经过人脑分析后,转换为一系列人的动作行为;而数据库中的解析模块要把用户的SQL表达的意图经过词法和语法分析,转换成程序可处理的数据结构。 这听起来还是很有意思的,那么我们现在就开始这第一步吧。 在开始之前再补充一些内容,整个开发过程主要使用C语言开发,在解析中会用到正则表达式和上下文无关语法,它们占比非常小。 开发所用的系统是CentOS 8.2,当然其它linux版本可能命令会有差异,Centos系列还是比较一致,可以看

By Ne0inhk
构建基于 Rust 与 GLM-5 的高性能 AI 翻译 CLI 工具:从环境搭建到核心实现全解析

构建基于 Rust 与 GLM-5 的高性能 AI 翻译 CLI 工具:从环境搭建到核心实现全解析

前言 随着大语言模型(LLM)能力的飞速提升,将 AI 能力集成到终端命令行工具(CLI)中已成为提升开发效率的重要手段。Rust 语言凭借其内存安全、零成本抽象以及极其高效的异步运行时,成为构建此类高性能网络 IO 密集型应用的首选。本文将深度剖析如何使用 Rust 语言,结合智谱 AI 的 GLM-5 模型,从零构建一个支持流式输出、多语言切换及文件批处理的 AI 翻译引擎。 本文将涵盖环境配置、依赖管理、异步网络编程、流式数据处理(SSE)、命令行参数解析以及最终的二进制发布优化。 第一部分:Rust 开发环境的系统级构建 在涉足 Rust 编程之前,必须确保底层操作系统具备必要的构建工具链。Rust 虽然拥有独立的包管理器,但在链接阶段依赖于系统的 C 语言编译器和链接器,尤其是在涉及网络库(如 reqwest 依赖的 OpenSSL)

By Ne0inhk