pub struct RdbmsRouting { /* private fields */ }Expand description
读写分离路由:写落主库、读落副本轮询,跳过熔断打开(Open)的副本。
只给每个端点包一层熔断是不够的:从库挂掉后轮询仍会把 1/N 的读转过去、 靠熔断快速失败 —— 那不是故障隔离,是稳定的 1/N 失败率(spec:235-236)。
Implementations§
Source§impl RdbmsRouting
impl RdbmsRouting
Sourcepub fn new(
primary: Arc<dyn RdbmsClient>,
replicas: Vec<Arc<dyn RdbmsClient>>,
) -> Self
pub fn new( primary: Arc<dyn RdbmsClient>, replicas: Vec<Arc<dyn RdbmsClient>>, ) -> Self
每个端点一个熔断器,配置取 BreakerConfig::default。
Sourcepub fn with_breaker_config(
primary: Arc<dyn RdbmsClient>,
replicas: Vec<Arc<dyn RdbmsClient>>,
cfg: BreakerConfig,
) -> Self
pub fn with_breaker_config( primary: Arc<dyn RdbmsClient>, replicas: Vec<Arc<dyn RdbmsClient>>, cfg: BreakerConfig, ) -> Self
显式指定各端点的熔断配置(冷却期、失败率阈值、窗口)。
Sourcepub fn fallback_to_primary(self, yes: bool) -> Self
pub fn fallback_to_primary(self, yes: bool) -> Self
副本全不可用时是否降级读主。默认 true;false 时读请求报
RdbmsError::NoAvailableReplica。
Trait Implementations§
Source§impl RdbmsClient for RdbmsRouting
impl RdbmsClient for RdbmsRouting
Source§fn transaction<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Transaction, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn transaction<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Transaction, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
事务天然读主(规避副本延迟),且不经熔断:事务失败由 SQL 层报错, 熔断器在这里只会把「主库慢」升级成「主库不可用」(spec §2.5 组合顺序)。
Source§impl SqlExecutor for RdbmsRouting
impl SqlExecutor for RdbmsRouting
Source§fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
sql: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<u64, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn execute<'life0, 'life1, 'async_trait>(
&'life0 self,
sql: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<u64, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
写 → 主库。
Source§fn query<'life0, 'life1, 'async_trait>(
&'life0 self,
sql: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn query<'life0, 'life1, 'async_trait>(
&'life0 self,
sql: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
读 → 副本轮询;全不可用时按 RdbmsRouting::fallback_to_primary 处置。
Source§fn execute_with<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<u64, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn execute_with<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<u64, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
写 → 主库。
Source§fn query_with<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_with<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
读 → 副本轮询;全不可用时按 RdbmsRouting::fallback_to_primary 处置。
Source§fn query_write<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_write<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
写路径的返回行查询(INSERT ... RETURNING)→ 主库:
落副本会读到陈旧数据。
Source§fn execute_then_query<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
first: &'life1 str,
first_params: &'life2 [Value],
second: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn execute_then_query<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
first: &'life1 str,
first_params: &'life2 [Value],
second: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Row>, RdbmsError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
两步式插入(MySQL 的 LAST_INSERT_ID())也是写路径 → 主库。
Auto Trait Implementations§
impl !Freeze for RdbmsRouting
impl !RefUnwindSafe for RdbmsRouting
impl !UnwindSafe for RdbmsRouting
impl Send for RdbmsRouting
impl Sync for RdbmsRouting
impl Unpin for RdbmsRouting
impl UnsafeUnpin for RdbmsRouting
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
Wrap the input message
T in a tonic::Request