当前位置: 首页 > news >正文

libmemcached库api接口讲解四

*_by_key 是 libmemcached 中一个相对高级但关键的概念,尤其在使用**一致性哈希(consistent hashing)**时,它决定了数据如何分布到服务器。下面我们来系统、全面地讲清楚它。


🧠 *_by_key 函数全面讲解


📌 一句话定义:

*_by_key 是 libmemcached 提供的一类函数,用于通过一个 “主键” (group_key)决定哈希路由位置(即数据该存到哪台 Memcached 服务器),而不只是根据实际操作的 key 决定。


🏗️ 它解决了什么问题?

假设场景:

你有以下数据:

用户 ID存储的 key
1001name
1001email
1002name
1002email

如果你直接使用 memcached_set()

memcached_set(memc, "name", ...);
memcached_set(memc, "email", ...);

那么:

  • nameemail 可能被路由到 不同的服务器,因为它们的 key 不同,哈希值不同。
  • 用户 1001 的两个字段可能跨了两台机器,造成分布不一致。

🛠️ 如何解决?

使用:

memcached_set_by_key(memc, "1001", 4, "name", 4, value, value_length, 0, 0);
  • 1001主 key(group_key)
  • name 是你实际的字段 key

现在,libmemcached 会:

使用 group_key 来做一致性哈希选择服务器,
使用 key 来存储具体的数据。

👉 这样,用户 1001 的所有 key(name, email…)都会路由到同一台服务器


📦 应用场景总结

应用场景是否使用 _by_key
普通缓存键值❌ 用普通 set/get
逻辑上属于同一“用户”、“session”、“商品”等的数据要存在一起✅ 强烈推荐使用 _by_key
分布式系统中缓存命名空间隔离✅ 可作为逻辑 namespace

🔁 对应函数对比

普通函数_by_key 函数是否支持 group_key
memcached_set()memcached_set_by_key()✅ 是
memcached_get()memcached_get_by_key()✅ 是
memcached_delete()memcached_delete_by_key()✅ 是

🧪 示例代码对比

不用 _by_key

memcached_set(memc, "user_1001:name", ..., ...);
memcached_set(memc, "user_1001:email", ..., ...);

这些 key 哈希后可能落在不同的服务器


_by_key

const char* group_key = "user_1001";
memcached_set_by_key(memc, group_key, strlen(group_key), "name", 4, value, val_len, 0, 0);
memcached_set_by_key(memc, group_key, strlen(group_key), "email", 5, value2, val_len2, 0, 0);

这些 key 会确保落到相同服务器,便于一致管理和快速访问。


🧩 为什么需要这样设计?

因为 Memcached 客户端做一致性哈希时,它只能对一个 key 做哈希,来决定“这条数据该放到哪台服务器”。而如果你希望逻辑上属于同一组的数据分布在一台服务器上,就需要提供一个统一的“分布依据”——这就是 group_key


⚠️ 注意事项

  • _by_key 并不会影响你在服务器端看到的 key,它只用于决定 hash ring 上服务器的选择
  • key 依然是你提供的 keygroup_key 仅参与路由。
  • 通常你只在需要跨字段聚合、保持分布一致性时才使用它。

📌 总结一句话:

如果你想让多个不同的 key 一定落在同一台 Memcached 服务器上,请用 *_by_key 系列函数,把统一的 group_key 提供给它。


怎么取数据

很好,这个问题非常关键。你通过 *_by_key 存储的数据,依然是用你原来的 key 来存的,只是客户端用 group_key决定该 key 分布在哪台服务器


✅ 简洁回答:

memcached_get_by_key() 来读取!你需要提供和写入时一样的 group_keykey


🧪 示例演示

1. 存储数据(使用 _by_key):

const char* group_key = "user_1001";   // 用来决定一致性哈希的节点
const char* key = "email";
const char* value = "user1001@example.com";memcached_set_by_key(memc,group_key, strlen(group_key),key, strlen(key),value, strlen(value),0, 0);

此时:

  • 数据存的是 "email" 这个 key
  • 它被放在了一台通过 "user_1001" 计算出来的服务器上

2. 读取数据(使用 _by_key):

size_t value_length;
uint32_t flags;
memcached_return rc;char* result = memcached_get_by_key(memc,"user_1001", strlen("user_1001"),"email", strlen("email"),&value_length,&flags,&rc);if (rc == MEMCACHED_SUCCESS && result != NULL) {printf("Got: %s\n", result);free(result); // 不要忘记释放内存
} else {printf("Get failed: %s\n", memcached_strerror(memc, rc));
}

🔁 必须用同样的 group_key,否则客户端可能去了一台错误的服务器,自然拿不到 key!


❓如果用普通 memcached_get() 可以吗?

不能保证能取到!

因为 memcached_get() 是用 key 做哈希选服务器,而你用 group_key 写入的数据可能在别的机器上了。

结果就是:

memcached_get(memc, "email", 5, ...);  // ⚠️ 可能失败(访问错服务器)

🧠 再总结一遍:

操作使用函数哈希依据能否成功
写入(指定 group)memcached_set_by_key()group_key✅ 正常存储
读取(指定同样 group)memcached_get_by_key()group_key✅ 正常读取
读取(不指定 group)memcached_get()key❌ 可能取不到

✅ 最佳实践

在使用 _by_key 写入时,始终使用 _by_key 读取、删除、替换等操作,并保持 group_key 一致。

🔍 为什么不直接用 group_key 作为 key?

你问的是:既然我们已经有 group_key 了,为什么还要额外指定一个 key?直接用 group_key 作为 key 不就完了?

我们用一个类比来解释这背后的设计初衷。


📦 类比:group_key 是“房间号”,key 是“抽屉名”

你可以想象:

  • group_key 是一个“房间号” → 决定这堆数据放在哪个房间(即服务器)
  • key 是房间里的“抽屉名” → 真正存取数据用的 key

所以:

memcached_set_by_key(memc, "user_1001", ..., "email", ..., value);

表示:
🗃️ “user_1001” 决定去哪个房间,
🔐 “email” 是房间里的 key,
📄 存的数据是 “user1001@example.com”


✅ 优点:支持“多个字段统一存储”

你可以将用户 1001 的多个字段统一放在一台机器:

memcached_set_by_key(memc, "user_1001", ..., "email", ...);
memcached_set_by_key(memc, "user_1001", ..., "name", ...);
memcached_set_by_key(memc, "user_1001", ..., "avatar", ...);

而不是每次把全部信息塞进一个 key 中,这样灵活性更强、结构更清晰。


❌ 如果只用 group_key,你会遇到的问题:

1. 无法存多个字段

你只能存一条记录,例如:

memcached_set(memc, "user_1001", ..., json_blob);

那么你必须把整个用户对象序列化为一个 JSON,一起读一起写,灵活性差。


2. 粒度太粗,不适合高并发写操作

不同系统模块可能只关心一个字段(如 email / name),如果把它们都合并成一个 key,意味着写任何一个字段,都要先取出、修改、再写回——非常低效。


3. 缺少灵活的数据访问

你想只更新或删除用户 email 就做不到了,必须操作整个 blob。


🧠 回答总结:

做法是否推荐原因
group_key + key✅ 推荐灵活、支持字段拆分、分布清晰
只用 group_key 当 key❌ 不推荐粒度粗、访问/更新不方便、读写效率低

🚀 设计哲学

libmemcached 的 _by_key 系列函数:

“路由逻辑”(group_key)“实际 key”(key) 分离开来,
实现灵活的逻辑分组 + 精准访问,更适合复杂业务场景。


相关文章:

  • Android锁
  • 【RabbitMQ】路由模式和通配符模式的具体实现
  • Canvas知识框架
  • OPC UA + ABP vNext 企业级实战:高可用数据采集框架指南
  • FlashInfer - SparseAttention(稀疏注意力)只计算部分有意义的注意力连接,而非全部 token 对
  • 文件(文件夹时间戳修改)最后修改时间变更
  • python打卡day25@浙大疏锦行
  • promise的说明
  • Minimum MPDU Start Spacing in A-MPDU
  • Spring Cloud:构建云原生微服务架构的最佳工具和实践
  • WhaleTunnel 信创数据库适配能力全景图:打通国产数据生态的最后一公里
  • 【Linux】shell内置命令fg,bg和jobs
  • 缺乏自动化测试,如何提高测试效率
  • 剖析提示词工程中的递归提示
  • Dockerfile实战:从零构建自定义CentOS镜像
  • UOS专业版上通过源码安装 Python 3.13 并保留系统默认版本
  • 关于并发编程AQS的学习
  • Python 之 Flask 入门学习
  • 计算机图形学之几何(Geometry)
  • Spring 事件监听机制的使用
  • 联合国秘书长欢迎中美经贸高层会谈成果
  • “降息潮”延续,多家民营银行下调存款利率
  • 波兰关闭俄罗斯驻克拉科夫领事馆
  • 总没胃口,一吃就饱……别羡慕,也可能是生病了
  • 射箭世界杯上海站摘得两银,中国队新周期冲击韩国缩小差距
  • 特朗普将启的中东行会如何影响伊美核谈判?专家分析