Redis不经常使用的结构-BitMap、GeoHash、HyperLogLog

首先呢,今天也是元旦的最后一天假期了,大家是不是在元旦的时候也给自己立了好多的目标呢,我呢,今年就立个小目标,争取,以后的每1~2周可以有时间来写一篇文章,不管好坏,希望在明年的这个时候自己的博客里面最少可以看得出来,自己今年的一些努力。

这里我就不说Redis的基本结构了,大家在平时的工作的时候都已经使用的滚瓜烂熟了,自己在平时的面试的时候想想也就能知道,我在面试过程中,这个五个基本类型都说不出来的几乎是没有的了。那么就来说说今天的主要的几个数据类型BitMap、GeoHash、HyperLogLog。

BitMap,位图,二进制里的一位一位的,这个平时的时候真的并不知道怎么使用的,使用过的地方好像就使用给用户的一个操作记录到这个里面,这个例子呢,我就不写了,如果小伙伴自己感兴趣可以去百度看看。

GeoHash,这是一个记录位置的数据结构,这里呢,我就写了两个小例子,一个是统计两个人之间的距离有多远,一个是附近的人的例子。

public static void main(String[] args) throws Exception{
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        jedis.geoadd("geomap_demo", 116.404269,39.91405, "张三");
        jedis.geoadd("geomap_demo", 116.417779,39.914382, "李四");
        jedis.geoadd("geomap_demo", 116.417707,39.916208, "王五");

        Double dis = jedis.geodist("geomap_demo", "张三", "李四", GeoUnit.KM);

        System.out.println("张三和李四的距离是:"+ dis + "KM");

        List<GeoRadiusResponse> geoRadiusResponses = jedis.georadiusByMember("geomap_demo", "李四", 2, GeoUnit.KM);
        geoRadiusResponses = geoRadiusResponses.stream().filter(resp -> !"李四".equals(resp.getMemberByString())).collect(Collectors.toList());

        System.out.println("李四附近2KM的人有:"+ geoRadiusResponses.stream().map(GeoRadiusResponse::getMemberByString).collect(Collectors.toList()));

    }

第一个是直接计算的张三和李四的距离是多少,我们直接把对应的经纬度找好了,然后复制就可以了,这个功能是不是有点像地图里面的距离某个地方多少KM的功能呢。

第二个是直接找到李四附近的人,前提是先把附近的人的坐标都输入好,然后在使用jedis.georadiusByMember,然后给号对应的值就可以了,这个功能是不是和附近人的功能很像。

 

HyperLogLog,这个的结构呢,是一个统计和去重使用的,但是呢,会有一定的误差,大概在1%左右的一个误差值。但是如果需要统计上百万,上千万的数据的时候,如果你要保证没有误差的话,使用Set的大小和使用HyperLogLog的大小,还是差很多很多的。第一个是可以统计网站的UV(浏览用户数),统计的时候还可以合并,还可以用作去重,这个可以用作大批量的去重。

public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        List<String> list = new ArrayList<>();
        for (int i = 100; i < 2000; i++){
            list.add(String.valueOf(i));
        }

        // 给hyper_demo_1用户的数据,大概1900个左右
        jedis.pfadd("hyper_demo_1", list.toArray(new String[list.size()]));

        // 这里统计对应的数据个数
        long count = jedis.pfcount("hyper_demo_1");
        System.out.println("统计UV的个数:" + count);


        // 给hyper_demo_2赋值
        list = new ArrayList<>();
        for (int i = 1900; i < 3000; i++){
            list.add(String.valueOf(i));
        }
        jedis.pfadd("hyper_demo_2", list.toArray(new String[list.size()]));

        // 给hyper_demo_3赋值
        list = new ArrayList<>();
        for (int i = 2900; i < 4000; i++){
            list.add(String.valueOf(i));
        }
        jedis.pfadd("hyper_demo_3", list.toArray(new String[list.size()]));


        // 这里"hyper_demo_1","hyper_demo_2","hyper_demo_3"合并到hyper_demo
        jedis.pfmerge("hyper_demo_0", "hyper_demo_1", "hyper_demo_2", "hyper_demo_3");
        // 这里看看hyper_demo最后的个数是多少
        count = jedis.pfcount("hyper_demo_0");
        System.out.println("统计合并后的UV的个数:" + count);

        // 这个地方第一次添加张三
        Long pfadd = jedis.pfadd("hyper_demo_n", "张三");
        System.out.println("添加张三是否成功:" + (pfadd == 1 ? "是":"否"));

        // 这个地方第二次添加张三
        pfadd = jedis.pfadd("hyper_demo_n", "张三");
        System.out.println("添加张三是否成功:" + (pfadd == 1 ? "是":"否"));

    }

第一个是就是直接去统计网站的UV数量,这个就是直接把数据放到里面看最后的结果就好了。

第二个是把好几个HyperLogLog都合并到一个里面,这个直接也会统计出来这几个里面去重后的结构,这个应用场景就是,我们每一天的UV都会记录下来,但是这个时候老板需要我们把这一周的UV给他,这个时候使用这个合并的功能就可以了。

第三个就是一个简单的去重的功能,在平时的工作中,如果遇到那种有很大批量的数据,你不知道怎么判断下一个是不是需要去重的时候,使用这个还是一个不错的选择的。

HyperLogLog其实在很多的场景面试题的时候回用到,这个就看大家遇到的时候会不会想到,虽然自己的答案并不一定是正确的,但是尽量保证的我们在面试的时候,面对这种场景面试题的时候,我们有我们自己的解题思路,这样面试官最少会多看一眼,你的机会也可以多一些。

我记得当初在我面试的时候,面试问过我一个问题,就是如果有一个上千万的商品详情页的数据存储在Redis里面,这个时候我是怎么来统计那个商品是在Redis里面的,那个是没有在这个里面的,当然这个里面需要注意的是,如果缓存里面的数据被LRU清楚了,这个HyperLogLog是并不知道的。

注:本人并没有什么大厂经验,如果有什么写的不好或者不对的地方还请见谅。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值