一、背景
有个需求需要将 SQL 语句作为分布式缓存的 key。 但是这样做会导致 key 太长。key 太长会有一些缺点。 但是 key 太长的问题也是可以解决的。 本文将详细讲述 key 太长的缺点和解决方案,希望对大家有帮助。
二、Key 太长的缺点
通常来说 SQL 作为 Key 太长,会有诸多缺点:
- Key太长会占用更多的内存空间,降低缓存的效率和命中率。
- Key太长会增加网络传输的开销,影响缓存的响应速度和吞吐量。
- Key太长会导致数据分片不均匀,增加缓存服务器之间的负载差异和数据迁移的成本。
- Key太长会增加缓存的管理和维护的难度,比如删除、更新、监控等操作。
因此,建议使用合理的Key设计规范,避免使用过长或者不必要的前缀、后缀、分隔符等。
三、解决方案
3.1 Hash (解决冲突问题)
可以使用哈希算法(如 MD5、SHA-1 等)将 SQL 语句转换成固定长度的字符串作为缓存 key。这种方式可以缩短 key 的长度,减小缓存空间占用,同时也可以提高查找效率。 但是,哈希算法可能存在冲突,需要注意缓存 key 的唯一性。
如何解决还冲突带来的唯一性问题?
- 加前缀,比如不同的租户、店铺的ID 或者 Code 作为 Key 的前缀,可以极大降低冲突的概率。
- 可以自定义值的结构 (1)将 SQL 存储在 Value 对象中,用于二次确认。 (2)如果原始的值是单个对象,可以定义为集合为。 通过 hash 值作为 key 读取出来值的时候对比当前 Sql 和 Value 中存储的 SQL 是否一致。 如果一致说明没有 Hash 冲突;如果不一致说明存在 hash 冲突,可以将新值放到集合中,读取时遍历集合取出对应的值即可。
伪代码如下:
代码语言:javascript复制public class Value{
String sql;
Object value;
}
public class CacheValueWrapper{
// 不冲突时存这里
Value value;
// 冲突时存这里
List<Value> values;
Value getValue(String sql){
// 先匹配 value
// 再匹配 values
}
}
3.2 语句映射(转化成唯一的值)
可以借助表的唯一键的特性。 新建一个映射表,包括 SQL 字符串、业务 Code (业务 ID)。
sql | id |
---|---|
select * from user where id=21 | 10086 |
select name,age from student where id=22 | 10087 |
业务Code 或者 业务 ID 可以使用数据库自增的特性也可以使用分布式 ID 生成器。 SQL 字符串设置为唯一键。 先通过 SQL 来查询,如果直接使用,如果表中没有这个 SQL 值则插入。
就可以将对应的业务 Code 或 业务ID 作为缓存 Key 的重要组成部分。
缓存Key: some_biz_prefix_10086
四、总结
本文提供一些解决 Key 过长的思路,希望对遇到相似问题的同学有启发。