【问题标题】:Implementing URL shortening with Cassandra使用 Cassandra 实现 URL 缩短
【发布时间】:2017-03-11 16:41:27
【问题描述】:

我正在尝试弄清楚如何使用 Cassandra 实现 URL 缩短服务。我有:

  • 3 个 cassandra 节点(在 Docker 上)
  • 将base10编码为base62数字(字符串)的函数

例如:

1 => a, 2 => b, 1205 => JR

这种方法的问题是我需要确定始终给出一个唯一的(递增的数字),以便下一个函数调用会给我一个唯一的字符串。

CREATE TABLE urls (
  id int PRIMARY KEY, // 1215 (auto increment)
  short_key text, // calculated short string from 1215
  url text, // real url
  created_at timestamp
) WITH CLUSTERING ORDER BY (created_at DESC);

使用DESC clustering,我总是可以从行中获取最后一个 id。这会产生一些问题:

  1. 每次写入前读取一行
  2. 如果你有很多写,所有 服务器必须知道下一个数字,即

你会如何解决这个问题?我试过用谷歌搜索解决方案,但在每个解决方案中我都发现了一个瓶颈。此外,哈希不是一种选择。

【问题讨论】:

标签: cassandra


【解决方案1】:

我不确定哪种性能适合您,但我可以建议以下基于 Cassandra 的解决方案:

您可以为每个用户服务器保留单独的计数器。每台服务器都分配有一个从 1 到 62 的唯一 ID(我想在您的情况下 62 台服务器就足够了)。 id 存储在服务器配置中的某个位置。您创建一个计数器表:

CREATE TABLE uniquecnt (
serverid int PRIMARY KEY,
cnt counter
) PRIMARY KEY (serverid)

当服务器启动时,它通过自己的 id 读取计数器值,并在每次请求新 id 时在内存中递增。此外,还需要在 Cassandra 中增加计数器。如果对 Cassandra 的更新无一例外地通过,则该值可用于 URL 生成。 (更新 Cassandra 时也至少使用 Quorum 一致性级别。)

对于 url 生成,您必须使用一种连接 domain +"/" + base62(serverId) + base62(counterValue)

在这种情况下,您的网址会稍长一些(1 个字母),但问题已解决。

在这里,我假设您能够在事务之间将计数器状态保存在每个服务器的内存中。此外,您不应在一台服务器的范围内并行更新计数器。

(通常你甚至不必使用计数器类型的表格。它也适用于简单的表格。)

【讨论】:

  • 顺便说一句,还可以进行优化。在每台服务器上,您可以提前更新 Cassandra 计数器 10 个数字: UPDATE uniquecnt SET cnt = cnt + 10 WHERE serverid=55;一旦您将这 10 个数字用于 URL,您就重复该操作。这样,您对 Cassandra 的写入将减少 10 倍。但在这种情况下,您无论如何都必须在 Cassandra 的其他地方单独记录您提供给用户的所有 URL。如果您的服务器崩溃,您将需要跳过您提供给用户的所有内容。这在实现上有点复杂,但可行。
【解决方案2】:

您正在尝试处理一个分布式计数器。正如您刚刚发现的那样,它们很难,C* 也无法解决这个问题,即使使用它的 counters 版本,因为您不能同时更新 读取计数器值.

我不是专家,但我建议您查看一些排队系统,例如 RabbitMQActiveMQKafka 等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    相关资源
    最近更新 更多