草庐IT

redis 减少 20-50 个字符长度的字符串键的内存消耗

coder 2023-07-18 原文

我有一个键是通过连接许多不同的元素生成的。:

[15,000 个唯一字符串] + [:] + [5 个唯一字符串] + [:] + [1 或 0] + [:] + [15,000 个唯一字符串] + [:] + [5 个唯一字符串] + [ :] + [1 or 0] = 长度在 20 到 50 个字符之间的字符串(例如:Vancouver:temp:1:Kelowna:high:0)

根据我的计算,将有大约 10 亿种组合,每种组合都是一把 key 。阅读 redis 文档(http://redis.io/topics/memory-optimization),他们建议您散列 key :例如。 "object:11558960"=> "1"可以变成 "object:1155""8960"=> "1"。

我正在考虑应用内存优化的最佳方法。我的第一个想法是为字符串创建一个数字表示。所以我会使用 MySQL 并创建查找表,其中每个字符串都有一个对应的数字整数。这样我可以更适本地散列,因为我可以比字符串更容易地划分数字。同样,这些数字会创建更短的键,我认为这会节省内存。这里的问题是 10 亿个键,这对 MySQL 来说是很大的开销,因为我必须创建连接等等。

我读到的另一种解决方案是获取我创建的字符串,然后在插入到 redis 之前使用 php 的 gzcompres 之类的工具对其进行压缩。 (http://labs.octivi.com/how-we-cut-down-memory-usage-by-82/)。

是否有任何最佳实践优化我可以用来降低我的 redis 内存消耗,因为目前它仍然太高?我愿意放弃 CPU 的能力来节省更多的内存。我的值只会是 0-50 之间的一位或两位整数。

最佳答案

查找表完全出问题了,别费心了。哈希解决方案似乎很适合您的需求。您可能希望您的 key 在 15,000 个唯一字符串之前立即拆分,以便为您提供足够的哈希 key ,使它值得付出努力。

所以代替:

SET Vancouver:temp:1:Kelowna:high:0 10

你会用

HSET Vancouver:temp:1 Kelowna:high:0 10

现在第一个 [1 或 0] 之后的所有内容都是哈希键,因此每个哈希大约有 150,000 个可能的键。

我对你的总 key 空间的计算与你的有点不同:

15000 * 5 * 2 * 15000 * 5 * 2 == 22500000000 (22.5 billion)

这样一来,您将拥有 150,000 个可能的键(redis 键),每个键都有 150,000 个可能的哈希键。

你在 redis key 和 hash key 之间做的间隔越靠左,hash key 的数字倾斜度就越大。例如,如果您将其拆分为

HSET Vancouver:temp 1:Kelowna:high:0 10

那么您将拥有 75,000 个用于散列的 Redis 键,每个散列可能包含 300,000 个键/值对。


另一种方法是使用整数值作为 key 。如果您的两组 15,000 个唯一字符串和 5 个唯一字符串中的每一个都有整数映射,那么您可以使用总共 34 位来表示任何 key 。例如。

 0000000000000   000   0   0000000000000   000   0
|      13     | | 3 | |1| |     13      | | 3 | |1|

这 13 位给出了 0-16383 的范围(涵盖了所需的 1-15,000) 这 3 位给出了 0-7 的范围(涵盖了所需的 1-5) 1 位为您提供所需的二进制 1 或 0 范围。

所以假设这些组成的值: 温哥华 == 9,987 温度== 3 基洛纳 == 3,454 高 = 2

你会:

(9987 << 21) + (3 << 18) + (1 << 17) + (3454 << 4) + (2 << 1) + (0 << 0)
==
20945229796

要从给定的键中取回值,您只需进行位移和屏蔽

20945229796 >> 20
9987

(20945229796 >> 4) & ((1 << 13) - 1)
3454

这是一个简单的 python 脚本,它将值转换为 int,并将 int 转换为值:

values = [9987, 3, 1, 3454, 2, 0]
bits =   [21, 18, 17, 4, 1, 0]

value_and_shift = zip(values, bits)


def key_from_values(values_and_shift):
    return sum(x << y for x, y in value_and_shift)

def extract_values(values_and_shift):
    last_shift = 35
    for value, shift in value_and_shift:
        print "Value should be:", value
        print "Value extracted:", (key >> shift) & ((1 << (last_shift - shift)) - 1)
        print
        last_shift = shift

key = key_from_values(value_and_shift)
print "Using value of:", key

extract_values(value_and_shift) 

输出

Using value of: 20945229796

Value should be: 9987
Value extracted: 9987

Value should be: 3
Value extracted: 3

Value should be: 1
Value extracted: 1

Value should be: 3454
Value extracted: 3454

Value should be: 2
Value extracted: 2

Value should be: 0
Value extracted: 0

关于redis 减少 20-50 个字符长度的字符串键的内存消耗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25858461/

有关redis 减少 20-50 个字符长度的字符串键的内存消耗的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  5. ruby-on-rails - unicode 字符串的长度 - 2

    在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

  6. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  7. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  8. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  9. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  10. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

随机推荐