通过redis散列存储和搜索

r7knjye2  于 2021-06-09  发布在  Redis
关注(0)|答案(2)|浏览(467)

我有大约一千万以上的电子邮件和电话号码用户。都指向一个用户id。我创建了2个哈希。一个用于电子邮件,另一个用于电话号码,如

//A single user with Both Email and Phone number pointing to same User ID
$redis->hSet('email-users', 'abc@xyz.com', 1);
$redis->hSet('phone-users', '+192938384849', 1);

现在有大约数百万的用户 Hash 正在变得过载,我也想搜索这些散列。就像我想从email用户的邮件中获取用户id一样。
我发现hash应该用redis中的ziplist来维护,这是存储一个大Map(字典)并划分成固定大小的小存储桶的最好方法,比如说一个hash中最多有10000个键。
所以,如果我把1000万用户分成10000个密钥桶,那么电子邮件大约有1000个哈希值,电话号码大约有1000个哈希值。
我的问题是,我应该把我的用户分成这1000个桶吗?如果是的话,那我怎么在这1000个桶里搜索呢?还是有更好的选择?
p、 我正在使用 PHP 获得所有1000个散列并循环它们可能需要大量的资源,而且我担心使用错误的方法也会降低系统的实际性能 Redis 权力。
作为一个补充,我认为我们可以创建一些算法,比如libketama,用于一致的散列,以便在随机服务器中放置密钥。
同样,如果在alphabats上工作很困难,我们可以先把每封邮件转换成数字,比如a=1,b=2,c=3。。。z=26,附加0(零)使其唯一,+s表示@和。角色。例如

abcd@gmail.com  ->  10203040+901301090+3015013

所以,现在我们有了数字,可以更容易地应用任何计算。

dl5txlt9

dl5txlt91#

你可以做的是根据第一个或前两个字母/数字来分配字母和数字。
您可以这样创建哈希;电子邮件首字母、电话号码首字母或前两位数字
电子邮件用户
电子邮件用户-b
电子邮件用户
电话-用户-10
电话-用户-11
当您进行hset/hget时,您可以在代码级别上安排它。
编辑:
假设我们将使用 first two digits 电话号码和 first two letters 电子邮件;
然后我们会有如下的钥匙;
电子邮件用户aa
电子邮件用户ab
电话-用户-11
电话-用户-12
当我们收到这样的邮件 ersoy@gmail.com 那我们就去 er 电子邮件哈希组 email-users-er 执行 hget email-users-er ersoy@gmail.com .
当我们有这样的电话号码 123456789 那我们就去 12 电话哈希组 phone-users-12 执行 hget phone-users-12 123456789 .

gc0ot86w

gc0ot86w2#

我的问题是,我应该把我的用户分成这1000个桶吗?如果是的话,那我怎么在这1000个桶里搜索呢?还是有更好的选择?
对。该方法可以按以下方式工作。
在本例中,我们将电话号码和电子邮件ID都视为字符串。
假设您有以下bucket(redis hash):

For Email Ids: email_0001, email_0002, ..., email_1000
For Phone Numbers: phone_0001, phone_0002, ..., phone_1000

给定一个email id,通过对email id进行散列来确定bucket(最大值为1000)。现在将键和值添加到相应的“bucket”中。

$ HSET "email_0032" "abc@xyz.com" "UID_987"

对电话号码重复步骤1。这就避免了您需要保留哪把钥匙进入哪一个桶。给定相同的键,散列将始终给出相同的值,从而返回相同的桶编号。

$ HSET "phone_0091" "+192938384849" "UID_987"

要检索一个值,首先通过对电子邮件/电话进行哈希运算来查找bucket,然后在适当的bucket中查找该值。

$ HGET "phone_0091" "+192938384849"
  UID_987
import java.nio.charset.Charset;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;

public class Sample {

    private static final int BUCKET_SIZE = 1000;
    private static final HashFunction hashFunction = Hashing.murmur3_128();
    private static final Charset UTF8 = Charset.forName("UTF-8");

    private Sample() {
    }

    public static int pickBucket(String key, int buckets) {
        int bucket = com.google.common.hash.Hashing.consistentHash(hashFunction.hashString(key, UTF8).asLong(), buckets);
        return bucket;
    }

    private static void getFromRedisHash(String key) {

        int bucket = pickBucket(key, BUCKET_SIZE);
        // Get From Redis based on the bucket number
    }

    public static void main(String[] args) {

        System.out.println(pickBucket("abc@xyz.com", BUCKET_SIZE));
        System.out.println(pickBucket("+192938384849", BUCKET_SIZE));
    }
}

上面的例子是用java编写的,我假设php会有类似的哈希库。

相关问题