fastsend.rs =========== # åˆ†å¸ƒå¼ ID å’Œåºåˆ—å·ç”Ÿæˆæ–¹æ¡ˆ ç”±äºŽä¸€äº›ä¼—æ‰€å‘¨çŸ¥çš„åŽŸå› ï¼Œè¶Šæ¥è¶Šå¤æ‚的环境è¦æ±‚我们需è¦ä¸€ç§ä¸ä¾èµ–或尽å¯èƒ½å°‘ä¾èµ–外部环境的 ID å’Œåºåˆ—å·ç”Ÿæˆæ–¹æ¡ˆï¼Œ 最早且最知å的解决方案是 Twitter æ出的雪花 ID 生æˆæ–¹æ¡ˆï¼ˆSnowflake ID 生æˆç®—法)。但对于 Snowflake, 我个人对其ä¸çš„一些实现方å¼å¹¶ä¸æ˜¯å¾ˆæ»¡æ„,包括但ä¸é™äºŽï¼š 1. 使用毫秒级时间戳,预计å¯ç”¨å¹´é™ä¸º 40 年,而我对程åºå¯ç”¨æ€§çš„è¦æ±‚是至少 100 年(虽然我å¯èƒ½ä¸€å®šæ´»ä¸åˆ° 100 å²ï¼‰ï¼› 2. Snowflake 的设计是为特别大é‡çš„并å‘考虑的,æ¯å°æœºå™¨æ¯æ¯«ç§’å¯ç”Ÿæˆ 1000 个 ID,而这也是我所ä¸éœ€è¦çš„ï¼ˆä¹Ÿå› æ¤ æˆ‘åœ¨è®¾è®¡ fastsend 时,仅è¦æ±‚æ¯ç§’ç”Ÿæˆ 65536 个 ID,相差了 100 个数é‡çº§ï¼‰ï¼› 3. 实时生æˆå¹¶æ— å¿…è¦ï¼Œå®Œå…¨å¯ä»¥é¢„先生æˆï¼ŒæŒ‰éœ€åˆ†é…(这ç§å®žçŽ°çš„一个必è¦æ¡ä»¶åœ¨äºŽï¼Œæˆ‘们并ä¸éœ€è¦ä»Ž ID ä¸èŽ·å–任何业务 相关的信æ¯ï¼Œä»…åªä½œä¸ºä¸€ä¸ªå”¯ä¸€æ ‡è¯†ç¬¦ï¼Œå¦‚果需è¦åŒ…å«ä¸šåŠ¡ä¿¡æ¯ï¼Œåº”使用åºåˆ—å·ï¼‰ï¼› åŸºäºŽä»¥ä¸Šå‡ ç‚¹ï¼Œæˆ‘è®¾è®¡äº†ä¸€ä¸ªç®€å•ä½†åˆéžå¸¸å®žç”¨ï¼ˆå¯¹æˆ‘而言)的 ID 生æˆæ–¹æ¡ˆï¼Œä¸éœ€è¦å€ŸåŠ©å¤–部系统(如数æ®åº“ã€ç¼“å˜ç‰ï¼‰ï¼Œä¾é 时间和自增åºåˆ—,以åŠä¸€äº›è¾…助信æ¯ï¼ˆå¦‚线程 IDã€è¿›ç¨‹ ID 和设备å·ç‰ï¼‰æ¥ç”Ÿæˆä¸€ä¸ªå…¨å±€å”¯ä¸€çš„ ID。åŒæ—¶ä¹Ÿæ供了åºåˆ—å·ç”Ÿæˆ 的实现方å¼ï¼Œä½†ç›¸è¾ƒè€Œè¨€ï¼ŒID 更快更高效,更具有通用性(åºåˆ—å·çš„生æˆä»Žå®žçŽ°è§’度上说也ä¾èµ–于 ID 生æˆï¼‰ã€‚ ## ID ID 被定义为一个 64 ä½æ— 符å·æ•´æ•°ï¼Œæ²¡æœ‰ä¸šåŠ¡å«ä¹‰ï¼Œå¸¸ç”¨ä½œæ•°æ®åº“主键,整数作为 ID å¯è¿›è¡Œé«˜æ•ˆçŽ‡çš„比较æ“作,这通常用于在 æ•°æ®é‡å¤§çš„查询场景进行查询速度的优化(虽然å—符串也能进行比较,但就效率而言,整数比较è¦æ¯”å—符串比较效率更高ã€é€Ÿåº¦æ›´å¿«ï¼‰ã€‚ åˆ†å¸ƒå¼ ID 生æˆå¹¶ä¸éœ€è¦ä¾èµ–å¤–éƒ¨ç³»ç»Ÿï¼Œä»…æœ‰ç®—æ³•æœ¬èº«åŠ ä¸Šæ—¶é—´æˆ³å³å¯ç”Ÿæˆä¸€ä¸ªå…¨å±€å”¯ä¸€çš„ ID,这也从å¦ä¸€æ–¹é¢å¼ºè°ƒäº† ID ç”Ÿæˆ çš„ç‰¹æ€§ï¼šé€Ÿåº¦å¿«ï¼æŒç»æ€§åœ°ç”Ÿæˆå¯é çš„ ID 是 fastsend çš„æ ¸å¿ƒåŠŸèƒ½ï¼Œfastsend 把 ID 抽象为一个独立的 trait(并为 ID æ供了默认实现 Token)其表现形å¼ä¸ºï¼š ```rust pub trait ID { fn id(self) -> u64; } ``` 这么åšçš„目的在于:也许在ä¸è¿œçš„å°†æ¥ï¼Œä¼šæœ‰å…¶ä»– ID 生æˆæ–¹å¼ï¼Œå±Šæ—¶ fastsend å°†æä¾›æ›´å¤šæ ·çš„ ID 生æˆæ–¹å¼ã€‚ ## Serial Serial å³åºåˆ—å·ï¼Œå…¶å®šä¹‰ä¸ºï¼šä¸€ä¸²åŒ…å«ç‰¹å®šä¸šåŠ¡å«ä¹‰çš„å—符串。åºåˆ—å·å’Œ ID ä¸€æ ·ï¼Œéƒ½å…·æœ‰å”¯ä¸€æ ‡è¯†æ€§ï¼Œä½†åºåˆ—å·åŒ…å«ä¸šåŠ¡ä¿¡æ¯ï¼Œ 我们å¯ä»¥ä»Žåºåˆ—å·ä¸è§£æžå‡ºç‰¹å®šçš„业务信æ¯ï¼ˆè€Œè¿™æ°æ˜¯ ID 所ä¸å…·å¤‡çš„),æ£æ˜¯ç”±äºŽåºåˆ—å·çš„ä¸šåŠ¡æ€§ï¼Œå› æ¤ç”Ÿæˆåºåˆ—å·ä¹Ÿæ¯”ç”Ÿæˆ ID è¦æ›´åŠ å¤æ‚,甚至需è¦å€ŸåŠ©å¤–部系统æ¥å®Œæˆã€‚考虑到通常情况下生æˆåºåˆ—å·å¯èƒ½åŒ…括必è¦çš„ IO æ“作,Serialer trait è¢«è®¾è®¡æˆ è¿”å›žä¸€ä¸ª Future ä»¥ä¾¿æ‹Ÿåˆ Rust 的异æ¥ä»»åŠ¡ç³»ç»Ÿã€‚fastsend æ供了 Serialer 的默认实现 TimeSerialer,并且为 Token 实现了 Serial 以供组åˆä½¿ç”¨ã€‚ ```rust use std::pin::Pin; pub trait Serialer { type Output: Display; fn build(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>>; fn feed(&mut self, data: &[u8]); } pub trait Serial { fn serial<S: Serialer>(self, serialer: &mut S); } ``` 关于 Serialer å’Œ Serial 详细的说明请å‚照这两个 trait 的注释。 # fastsend 注æ„事项 ## feature fastsend æ供了 'pause_on_start' feature,用于在程åºå¯åŠ¨æ—¶æš‚åœè‡³ä¸€ä¸ªæ–°çš„时间节点,以é¿å…é€ æˆ ID å’Œåºåˆ—å·ç”Ÿæˆ 冲çªï¼Œè¿™åœ¨ä»£ç 注释ä¸æœ‰è¯¦ç»†è¯´æ˜Žã€‚pause_on_start 是默认 feature,在分布å¼åœºæ™¯ä¸‹ï¼Œpause_on_start 是ä¿è¯ fastsend 稳定å¯é çš„é‡è¦ä¿è¯ä¹‹ä¸€ã€‚但在命令行程åºä¸ï¼Œpause_on_start å¯èƒ½ä¼šä¸å¯é¿å…åœ°é€ æˆç¨‹åºå“åº”æ—¶é—´è¿‡é•¿çš„é—®é¢˜ï¼Œå› æ¤åœ¨å‘½ä»¤è¡Œ 应用ä¸ï¼Œç¦ç”¨æŽ‰é»˜è®¤ feature 是一个æ£ç¡®çš„选择,但æ¤æ—¶å¿…须由调用方æ¥é¢å¤–确认生æˆçš„ ID 或åºåˆ—å·æ˜¯å¦æ˜¯å…¨å±€å”¯ä¸€çš„。 ## 环境å˜é‡ fastsend 需è¦é…置两个环境å˜é‡ï¼Œåˆ†åˆ«æ˜¯ `FASTSEND_RANDOM_VALUE` å’Œ `FASTSEND_DEVICE_ID`,分别在编译时和è¿è¡Œæ—¶ 使用。 å…¶ä¸ï¼Œ'FASTSEND_RANDOM_VALUE' 用于编译时确定程åºä¸çš„éšæœºæ•°åŸºç¡€ï¼Œè¿™ä¸ªéšæœºæ•°åŸºç¡€æŒ‡çš„是:该éšæœºæ•°ä¼šç”¨äºŽåœ¨ç¨‹åºä¸ 对å„项数值进行混淆(包括环境å˜é‡ 'FASTSEND_DEVICE_ID'),é¿å…被攻击者嗅探到程åºä¸çš„æŸäº›ç‰¹å®šå€¼ã€‚'FASTSEND_RANDOM_VALUE' 是程åºå¿…é¡»æ供的值,如果未在环境å˜é‡ä¸æ供该值,则程åºè¢«è§†ä¸ºå•åº”用程åºï¼Œå°†é€šè¿‡ 'rand' 生æˆä¸€ä¸ªéšæœºå€¼ã€‚注æ„,如果任由 程åºç”Ÿæˆéšæœºå€¼ï¼Œå¹¶éƒ¨ç½²åœ¨å¤šè®¾å¤‡çŽ¯å¢ƒï¼Œå¯èƒ½å¯¼è‡´æœ€ç»ˆäº§ç”Ÿçš„è®¾å¤‡å· 'FASTSEND_DEVICE_ID' é‡å¤ï¼Œé€ æˆ ID 生æˆé‡å¤ã€‚ 'FASTSEND_DEVICE_ID' 则是用于在è¿è¡Œæ—¶ç¡®å®šè®¾å¤‡å”¯ä¸€ ID 的环境å˜é‡ï¼Œç”¨äºŽåœ¨åˆ†å¸ƒå¼çŽ¯å¢ƒä¸ç¡®å®šè®¾å¤‡å”¯ä¸€æ€§ã€‚如果 fastsend 程åºåº”用于 多多设备(分布å¼ï¼‰çŽ¯å¢ƒï¼Œé‚£ä¹ˆä½ 应该ä¿è¯æ¯å°è®¾å¤‡ä¸Šçš„ 'FASTSEND_DEVICE_ID' 都互相独立,å„ä¸ç›¸åŒï¼Œå¯¹äºŽ 'FASTSEND_DEVICE_ID' 的读å–是在程åºè¿è¡Œæ—¶ï¼Œä½†ä»…会在程åºåˆå§‹åŒ–时读å–一次。设备 ID 在程åºè¿è¡Œè¿‡ç¨‹ä¸ä¸æ˜¯å¿…é¡»çš„ï¼Œå› æ¤å®ƒä»¥ `Option` çš„å½¢å¼å˜åœ¨äºŽä»£ç ä¸ï¼Œ 在å•åº”用程åºä¸ï¼Œå¦‚æžœä¸æƒ³æ供设备 ID,那么当程åºç›‘æµ‹åˆ°æ— 'FASTSEND_DEVICE_ID' 环境å˜é‡æ—¶ï¼Œä¼šé‡‡ç”¨å…¶ä»–æ–¹å¼æž„建 ID(例如进程å·ï¼‰ï¼Œ å› æ¤åœ¨å¤šè®¾å¤‡åœºæ™¯å¦‚果未æ供设备 ID,那么很å¯èƒ½é€ æˆ ID 生æˆé‡å¤ã€‚设备 ID 会使用上述æ到的 'FASTSEND_RANDOM_VALUE' 值进行混淆 以é¿å…设备å·è¢«æ¶æ„嗅探。 # TODO - [ ] 实现更多 `Serialer` - [X] `TicketSerialer` - [X] `UUIDSerialer` - [X] `Random62Serialer`