You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust Diesel插入冲突时执行Redis自定义存储逻辑可行吗?

解决方案:插入冲突时将文章存入Redis

可以实现这个需求,下面提供两种实用的方案,适配你当前的Diesel 2.0.4版本:

方案1:在Rust代码中判断插入结果,触发Redis存储

这是最直接且易维护的方式,利用Diesel插入操作的返回值判断是否发生冲突,再执行Redis写入逻辑。

实现步骤:

  1. 执行插入语句,通过execute返回的受影响行数,或returning的结果是否为空,判断是否冲突。
  2. 若判定为冲突(插入未生效),将文章序列化为JSON后存入Redis。

代码示例:

use diesel::prelude::*;
use redis::Commands;
use serde::Serialize;

// 假设你的文章结构体实现了Serialize trait
#[derive(Insertable, Serialize)]
#[diesel(table_name = articles)]
struct NewArticle {
    id: i32,
    title: String,
    content: String,
    // 其他字段...
}

fn insert_article_or_save_to_redis(
    article: NewArticle,
    db_conn: &mut PgConnection,
    redis_conn: &mut redis::Connection,
) -> Result<(), Box<dyn std::error::Error>> {
    // 执行插入,返回受影响的行数
    let inserted_rows = diesel::insert_into(articles::table)
        .values(&article)
        .on_conflict_do_nothing()
        .execute(db_conn)?;

    if inserted_rows == 0 {
        // 无行受影响,说明发生冲突,存入Redis
        let article_json = serde_json::to_string(&article)?;
        redis_conn.set(format!("article:{}", article.id), article_json)?;
    }

    Ok(())
}

注意事项:

  • 高并发场景下可能存在竞态条件:比如线程A执行插入前数据不存在,线程B先完成插入,线程A执行插入时返回冲突,但此时数据已存在。若业务对强一致性要求高,可结合数据库事务或行级锁,但会牺牲部分性能。

方案2:利用PostgreSQL触发器处理冲突(数据库层面)

通过PostgreSQL的触发器机制,在插入冲突时触发自定义逻辑将数据写入Redis。这种方式无需修改太多Rust代码,但依赖数据库扩展,维护成本较高。

实现思路:

  1. 安装PostgreSQL的Redis扩展(如pg_redis或redis_fdw)。
  2. 创建PL/pgSQL函数,将冲突数据写入Redis。
  3. 在INSERT ... ON CONFLICT语句中通过间接方式触发该函数(Diesel 2.0.4暂不支持ON CONFLICT DO CALL,可通过DO UPDATE SET配合触发器实现)。

示例SQL(需适配你的表结构):

-- 假设已安装pg_redis扩展
CREATE OR REPLACE FUNCTION save_article_to_redis()
RETURNS TRIGGER AS $$
BEGIN
    -- 将冲突的文章数据序列化为JSON存入Redis
    PERFORM redis_set(CONCAT('article:', NEW.id), row_to_json(NEW));
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- 创建触发器,当插入冲突时触发
CREATE TRIGGER trigger_article_conflict
AFTER INSERT ON articles
FOR EACH ROW
WHEN (NOT FOUND) -- 仅在插入未成功时触发
EXECUTE FUNCTION save_article_to_redis();

优缺点:

  • 优点:Rust代码无需额外逻辑,冲突处理逻辑集中在数据库。
  • 缺点:依赖特定数据库扩展,调试和迁移难度大,灵活性不如Rust代码层面处理。

推荐方案

优先选择方案1,逻辑清晰、易调试,且能更好地与Rust业务代码集成。若业务对数据库层面的冲突处理有特殊需求,再考虑方案2。

内容的提问来源于stack exchange,提问作者Dolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 22:05:05