redis的应用场景

心已入冬 提交于 2020-03-04 04:09:16

                          redis的应用场景

目录

1、充值订单超时队列

2、缓存系统

3、计数器

4、消息队列系统

5、Bitmap

6、HyperLogLog

7、list集合的使用

8、hash的使用

9、sunionstore


1、充值订单超时队列

创建充值订单时,将订单号chargeOrderId、账号信息id、超时开始时间timeoutCreateTime添加进redis。用getRedisKey方法将两个参数组建成一个可以切割的key,可以中间加上分割符号“:”

redisClusterClient.zadd("NEW_CHARGE_ORDER", timeoutCreateTime, getRedisKey(chargeOrderId, id));

在项目中创建一个ChargeOrderTimeoutTimerTask任务,用quartz进行处理,定时按周期执行该定时任务

public void run() {
        long orderTimeout = 3 * 60 * 1000;
        long time = new Date().getTime() - orderTimeout;
        Set<String> set = redisClusterClient.zrangeByScore("NEW_CHARGE_ORDER", 0, time);
        for(String key : set){
            //进行逻辑处理,将待支付状态的充值订单修改为订单关闭状态
           redisClusterClient.zrem("NEW_CHARGE_ORDER", key);
        }
}


2、缓存系统

例如,缓存视频的基本信息

public VideoInfo get(long id) {
    String redisKey = redisPrefix + id;
    Map<String, String> hashMap = redis.hgetAll(redisKey);
    VideoInfo videoInfo = transferMapToVideo(hashMap);
    if (videoInfo == null) {
        videoInfo = mysql.get(id);
        if(videoInfo != null) {
            redis.hmset(redisKey, transferVideoToMap(videoInfo));    
        }
    }
}

redis存储用户信息的三种方式:
1、String类型,value存储json串
2、String类型,很多个key,每个key对应一种属性
3、Hash类型,设置一个key,将filed存储为属性,value为对应的值。
方式比较:
 

 

3、计数器

incr (单线程:无竞争)
1)记录网站每个用户个人主页的访问量?(用hash,例如: hincrby user:1:info  pageview  count)

2)用来创建充值订单号
      通过redis获取到自增值,能保证创建的订单的唯一性,后续可以再在前面加上时间戳和业务相关的订单属性,拼接成一个完整的订单号。

    public Long getIncrChargeId() {
        return redisClusterClient.incr("CHARGE_INCR_KEY");
    }

    public void setIncrChargeId(long id) {
        redisClusterClient.set("CHARGE_INCR_KEY", String.valueOf(id));
    }
    
    public Long getChargeOrderId() {
        Long incrId = 10000000L;
        try{
            incrId = getIncrChargeId();
            if (incrId < 10000000 || incrId > 99999999) {
                synchronized (Charge.class) {
                    incrId = getIncrChargeId();
                    if (incrId < 10000000 || incrId > 99999999) {
                        setIncrChargeId(10000000L);
                        incrId = getIncrChargeId();
                    }
                }
            }
        } catch(Exception e){
            incrId = 10000000L + new Random().nextInt(90000000);
        }
        return incrId;
    }





4、消息队列系统

blpop brpop
blpop key timeout #lpop阻塞版,timeout是阻塞超市时间,timeout=0永远不阻塞, 时间复杂度O(1)
1、LRUSH + LPOP = Stack
2、LPUSH + RPOP = Queue (将id加入队列,然后用线程池进行捞取id 进行后续处理)
3、LPUSH + LTRIM = Capped Collection  (控制获取列表的大小)
4、 LPUSH + BRPOP = Message Queue (消息队列)

 

5、Bitmap

相关命令
setbit key offset value  #给位图指定索引设置值
getbit key offset  #获取位图指定索引的值
bitcount key [start end] 获取位图指定范围(start 到end, 单位为字节,如果不指定就是获取全部)位值为1的个数
bitop op destkey key [key...] #做多个bitmap的and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在destkey中
bitpos key targetBit [start][end] #计算位图指定范围(start到end, 单位为字节,如果不指定就是获取全部)第一个偏移量对应的值等于targetBit的位置

独立用户统计
1、使用set和Bitmap
2、1亿用户,5千万独立
 

只有10万独立用户呢(因为bitmap得占有全部的用户数)


使用​​​经验
​​​​1)type = string, 最大512MB
2)注意setbit时的偏移量,可能有较大耗时
3)位图不是绝对好


6、HyperLogLog


 可以用来统计累计系统用户数(不需要太精确)

1、极小空间完成独立数量统计,是一个数学算法
2、本质还是字符串
3、3个命令
pfadd key element [element...]:向hyperloglog添加元素
pfcount key[key...] : 计算hyperloglog的独立总数
pfmerge destkey sourcekey [sourcekey ...] : 合并多个hyperloglog

4、使用经验
1)错误率:0.81%
2)无法取出单条数据
 

7、list集合的使用


 后台管理系统可以用list用来存储后台折线图的数据,redisKey 可以由年份 + 统计的类型(如充值人数)+ 业务类型(游戏)组成, 集合的大小可以设置为365或者366个,对应天数,第三个参数为数值。这样就可以通过redisKey获取哪个年份哪一个月的时间范围内的游戏业务充值人数了。

//向list集合插入数据
redisClient.lset("redisKey", 1, "1");
// 获取list集合的所有数据
List<String> re = redisClient.lrange("redisKey", 0, -1);

 

8、hash的使用

后台管理系统可以用hash进行存储对应时间段的图标数据
每天跑定时任务,获取到的数据都记录在一张统计表上,通过查询对应时间段的业务数据,用redis的hset进行存储。
redisKey可以有两个时间段进行拼接, hash的field为统计类型 + 业务类型进行拼接, value为对应的值,组成map。

// 查询该时间段内的数据
Map<String, String> hash = dataQuery.query(startDate, endDate);
    redisClient.hmset(redisKey, hash);
// 获取时间段内的业务数据,比如说一个月
    Map<String, String> map = redisClient.hgetAll("redisKey");


9、sunionstore

keysArray为多个类型为Set<String> 的key的数组,将他们进行聚合,得到一个包含全部值的set,存入Set<String> setKey, 返回set的数据大小countValue.

countValue = redisClient.sunionstore(setKey, keysArray);

温馨提示:该指令最好不要使用,时间复杂度为 O(n), 计算时间非常耗时,而且 将大量的Set数据存入Redis,是非常吃内存的,Redis服务器的价格是按分配内存大小进行计费的。所以后来,花了一些时间,将涉及该指令的代码进行优化,尽量不用到他,或者只是小部分数据用到它。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!