我的应用程序是一个游戏,我需要每个用户能够创建一个唯一的,自然的数字ID代码,可以像url-shortener一样双向地转换为“短字符串”。 “短串”部分对游戏非常重要。
我考虑过创建一个带有auto-id键的子节点,该键存储自然数索引&短字符串和另一个包含自然数作为键和前一个自动标识键的子节点。
我很担心在两个用户同时创建新ID的情况下出现竞争条件。理想情况下,我希望能够从1000开始递增ID以保持短字符串非常短。
有没有人知道使用firebase-database解决这类问题的好方法?
我希望将“短字符串”保留在6个字符以下,并且只使用数字,大写字母和连字符。 (所以一个34个字符的字母表,为清晰起见省略1s,ls,Os和0)
也许这是不可能的,我将不得不使用50个字符的字母来生成随机数并将其添加到每个键。
一个想法是检查当前最高密钥并生成一个随机数添加到该密钥,但仍然无法保证两个用户不会得到相同的数字。
到目前为止,如果两个用户同时尝试生成新密钥,那么我唯一可能阻止竞争条件的另一个想法是保留在线用户的内部列表,并在每个用户的子节点中创建密钥并在发布到数据库之前有延迟....要求用户检查所有其他用户的请求密钥。
这最后一个想法似乎令人费解并且容易出错,每次用户重新连接时都需要代码检查列表,以防他们上次在线时丢失连接。
答案 0 :(得分:2)
hashids
是一个将数字转换为短字符串并返回的小脚本(请参阅http://hashids.org/)。
通过这种方式,您可以简单地使用增量计数器,并将它们转换为短字符串。
我通过拥有一个中央“计数器”节点在Firebase中使用它,该节点只能递增1(使用安全规则)。客户端可以使用事务将此节点增加1。结果编号将保证该客户端的唯一编号。 (请注意,如果两个客户端完全同时触发事务,则事务块中的代码可以多次触发。因此,您需要使用事务创建的最终数字。)
然后,该客户端的唯一编号可以与hashids
一起使用,以创建一个也保证唯一的短字符串。
注意:这并不能解决用户可以猜出下一个ID的“问题”。如果您具有用于创建字符串的salt
,则可以将短字符串转换回数字。然后,使用hashids
函数可以轻松生成下一个短字符串。因此,如果您在客户端中创建短字符串,则salt
在客户端中也是已知的,因此可以由用户提取。
当然,根据您的情况,这可能不是问题。
答案 1 :(得分:0)
所以我终于想出了解决这个问题的方法。
我也在创建该应用的Android版本,因此必须找到在Android中执行此操作的等效方法。
我所做的是使用事务块来递增计数器。每次计数器成功递增时,它都会运行一个完成块,用于更新相应的子节点。
当同一用户希望一次执行多个增量时,会出现下一个问题。 (这种情况不会经常发生,但确实会发生)
事务块每个都获得自己的线程,但是完成块将在主线程上排队,等待事务全部完成。
使用GCD我可以使用DispatchQueue为每个增量操作赋予自己的线程。现在,用户可以执行他们需要的许多增量,并保证拥有与其项目对应的唯一HashId跟踪代码。
我最终在Firebase Slack小组中获得了一些帮助......这是寻找积极讨论的好地方!
干杯!