新手问题 请问如何生成形如 “V2UJY1FlBzdTbVI9” 这样的字符串来作为主键?

Insub · 2020年04月16日 · 最后由 xiaogui 回复于 2020年04月23日 · 1686 次阅读

如题,看到穷游的主键是这种形式的,请教下应如何生成形如 “V2UJY1FlBzdTbVI9” 这样的主键? https://place.qyer.com/poi/V2UJY1FlBzdTbVI9/

base xx

看着长度不像是 BASExx ?

Ruby 标准库有 SecureRandom.alphanumeric

p SecureRandom.alphanumeric(16) => "5Ov39BS5Ve0n4CET"
p SecureRandom.alphanumeric(24) => "CabSW7ijP9Hg1CojBziVajP9"

Rails API 里面有个 Base58

https://api.rubyonrails.org/classes/SecureRandom.html#method-c-base58

p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"

如果你不希望有大写字母,可以用 Base36

https://api.rubyonrails.org/classes/SecureRandom.html#method-c-base36

p SecureRandom.base36 # => "4kugl2pdqmscqtje"
p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"

以上有重复概率,在插入的时候处理唯一错误,重试

hashids 可以

6楼 已删除
require 'securerandom'
SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"

https://ruby-doc.org/stdlib-2.2.10/libdoc/securerandom/rdoc/SecureRandom.html#method-c-hex

xiaorong 的 hex 应该是 OK 的。

base xx 要注意是不是 url safe 的。

因为是用来做标识的,需要在插入时不重复,并且不可逆,不知道大家是怎么处理的? 我准备用一个创建后的钩子对应数据库 ID 来生成这个对外的 ID

Insub 回复

你不嫌弃的话可以看下我做的 url 短链接服务利用数据库主键 id 生成唯一短链接的 ruby 代码 https://github.com/printfinn/url_shortener/blob/master/app/models/link.rb。 这个可以保证不重复,而且(按我的理解)是 O(1) 的时间复杂度。 不知道你说的不可逆是指啥?逆回主键 id 吗?不可逆不知道,但可以做到防止遍历。比如可以考虑给这个 f(id) 前面加两位 prefix:

prefix = f(h(id) % (62 ** 2))
uid = "#{prefix}#{f(id)}"

f(x) 是数据库主键 id 转 a-zA-Z0-9 的函数

h(x) 可以是你设计的 hash function,别人猜不到你的 hash,也就无法遍历了

补充:如果你想不可逆,其实也容易,就是在设计 f(x) 时候不要按 a-zA-Z0-9 的顺序对应,而是自己设计一个表来查表,比如原来 0 对应 a,25 对应 z,26 对应 A,61 对应 9,你更改一下自己的映射表,比如 0 对应 f, 25 对应 8,总之不要被人猜出你的表就可以了。

loop do
  key = generate_unique_key
  break key if db_not_exists?(key)
end

简单粗暴

@FinnG 是我表述错误了,应该是 “可逆,但不易被直接解码而后被遍历” 你所给出的解决方案正是我要的,非常感谢~

hashids + 1

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册