redis解决大数据_redis大数据量解决方案 - CSDN
  • 感谢同事的分享。 很多同事不是很清楚redis可以干嘛,这边就简单的聊下。... 首先从基础开始,什么是redis,它和我们常说的NOSQL是什么关系...Redis 是一个内存中的数据结构存储系统,它可以用作数据库,缓存和消息
      
    转载:http://aodi.paic.com.cn/forum.php?mod=viewthread&tid=5232&fromuid=1
    感谢同事的分享。
    很多同事不是很清楚redis可以干嘛,这边就简单的聊下。
         首先从基础开始,什么是redis,它和我们常说的NOSQL是什么关系?

    Redis 是一个内存中的数据结构存储系统,它可以用作数据库,缓存和消息中间件。说白了主要就是用来缓存数据。
    而NOSQL从字面意思来看是  not only SQL,意思就是运用非关系型的数据存储。REDIS也是NOSQL数据库的一种,
    并不是说不使用SQL语句,很多封装方法后,用起来和普通的SQL语法一样样的。

          那么他如果操作,能实现什么呢?
           String ,Hash ,List ,Set,Sorted set 5 常用的数据类型,并且有持久化功能。


    在JAVA封装后,你可以像操作java常用的数据类型一样去操作REDIS。
    具体的5种特性属性,这里就不介绍了。有意者随便百度下。

    Redis是单线程的,但是,处理速度非常的快。可以用redis做为一个消息队列,个人觉得它属于轻量级的,没有ACTIVEMQ那些繁重。
    数据提交可以操作 pipline进行批量的处理数据,进行异步的提交。速度杠杠的。
    redis在缓存的定义上是真正意义上的内存式缓存。不像MongoDB,利用索引,海量数据的存储镜像需要存在磁盘上或虚拟内存上。而
    redis通过算法,将常用的数据类型,放在内存里,将不常用的进行持久化,移出内存空间。这个机制,非常类型JAVA的VM,了解新生代,
    老年代,持久代的定义后,就不难理解redis的这个机制了。
    Redis将内存的保存地址进行哈希排序,标记产生哈希槽。Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 取模,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。所以需要配置 内存的maxmemory策略,以免内存达到极限。
    使用哈希槽的好处就在于可以方便的添加或移除节点。
    当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;
    当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了。
    集群、主备防灾说的通俗点就是 对 哈希槽 的监管权的拥有。如果主有问题,就快速死掉,把哈希槽的拥有权给备机监管。
    在持久化的时候,有2种方式:AOF和RDB。
    RDB是可以配置指定的时间间隔对数据进行快照存储。
    而AOF持久方式是对REDIS进行写的操作都进行存储。意思就是实时备份,所以通常
    情况下AOF文件的数据集要完整一些。

    那我们为什么要用它?
       既然REDIS是一种缓存管理工具。它当然可以取代现有一些CACHE的工具。
    那我们到底怎么使用它能够给我们带来巨大的收益呢?
    我们会在什么样的场景下使用它?看下这个逻辑金字塔模型,能够稍稍的解释一些使用

    这3个分层的金字塔三角形,从底层开始说,第3层 游客,就是说客户随意逛逛,粘合度不高的,不会最终交易。第2层就是有自己喜好的,对这边有感兴趣的点。可以下单,但不一定会买。第一层金字塔顶层,就是 忠实客户会购买喜欢的产品。
    可以看出整个流量数据是 第一层往后越少。
    而实际应用中,如果所有的信息读写都是来自数据库的话,I/O的所有负担都压在了数据库上,而真正业务是要实现快速交易。流量一旦上来,发现查询也查不了,交易也交易不了,都堵塞了。所以并不是所有的操作都需要去访问数据库,这种海量数据下非常容易击穿数据库。导致生产事故。

    在这样大数据量的频繁查询下,这个场景下,REDIS就派上了用场。

    Redis缓存客户信息,用session id或者有access_token做为keyexpire 时间为30分钟。
    而网站信息缓存信息,产品说明等。这样 就把大部分的流量拦截了下来,数据库的I/O解放了出来,
    客户最先登录后,就把页面显示的信息,个人信息都缓存好了。无论怎么刷新,
    退出登录都不会访问到数据库了。 数据库可以专心的等待交易的进行。
    当然缓存的信息都是不常改变的,如产品说明,列表等等这些,另外的像客户信息如购买了产品后,
    记得更新缓存,因为产品列表,个人信息发生了变化。
    在分布式环境里,nginx作为负载均衡,轮询服务器,redis做为 分布式会话缓存工具 尤其常见。
    再加上一些静态页面的处理,动静态分离,数据库读写分离,Java虚拟机的优化,TOMCAT容器的优化
    等等,大数据量下的优化措施能把以前的拖拉机变成豪华飞机。有机会再讲下现在常见的分布式大型网站的建设
    今天到此结束,码字辛苦,谢谢。
    展开全文
  • 今天将会跟大家讨论一些Redis大数据中的使用,包括一些Redis的使用技巧和其他的一些内容。一、Redis封装架构讲解实际上NewLife.Redis是一个完整的Re...

    今天将会跟大家讨论一些Redis在大数据中的使用,包括一些Redis的使用技巧和其他的一些内容。

    一、Redis封装架构讲解

    实际上NewLife.Redis是一个完整的Redis协议功能的实现,但是Redis的核心功能并没有在这里面,而是在NewLife.Core里面。

    这里可以打开看一下,NewLife.Core里面有一个NewLife.Caching的命名空间,里面有一个Redis类,里面实现了Redis的基本功能;另一个类是RedisClient是Redis的客户端。

    Redis的核心功能就是有这两个类实现,RedisClient代表着Redis客户端对服务器的一个连接。Redis真正使用的时候有一个Redis连接池,里面存放着很多个RedisClient对象。

    所以我们Redis的封装有两层,一层是NewLife.Core里面的Redis以及RedisClient;另一层就是NewLife.Redis。这里面的FullRedis是对Redis的实现了Redis的所有的高级功能。

    这里你也可以认为NewLife.Redis是Redis的一个扩展。

    二、Test实例讲解Redis的基本使用

    1、实例

    打开Program.cs看下代码:

    这里XTrace.UseConsole();是向控制台输出日志,方便调试使用查看结果。

    接下来看第一个例子Test1,具体的我都在代码中进行了注释,大家可以看下:

    Set的时候,如果是字符串或者字符数据的话,Redis会直接保存起来(字符串内部机制也是保存二进制),如果是其他类型,会默认进行json序列化然后再保存起来。

    Get的时候,如果是字符串或者字符数据会直接获取,如果是其他类型会进行json反序列化。

    Set第三个参数过期时间单位是秒。

    vs调试小技巧,按F5或者直接工具栏“启动”会编译整个解决方案会很慢(VS默认),可以选中项目然后右键菜单选择调试->启动新实例,会只编译将会用到的项目,这样对调试来说会快很多。

    大家运行调试后可以看到控制台输出的内容:向右的箭头=》是ic.Log=XTrace.Log输出的日志。

    字典的使用:对象的话,需要把json全部取出来,然后转换成对象,而字典的话,就可以直接取某个字段。

    队列是List结构实现的,上游数据太多,下游处理不过来的时候,就可以使用这个队列。上游的数据发到队列,然后下游慢慢的消费。另一个应用,跨语言的协同工作,比方说其他语言实现的程序往队列里面塞数据,然后另一种语言来进行消费处理。这种方式类似MQ的概念,虽然有点low,但是也很好用。

    集合,用的比较多的是用在一个需要精确判断的去重功能。像我们每天有三千万订单,这三千万订单可以有重复。这时候我想统计下一共有订单,这时候直接数据库group by是不大可能的,因为数据库中分了十几张表,这里分享个实战经验:

    比方说揽收,商家发货了,网点要把件收回来,但是收回来之前网点不知道自己有多少货,这时候我们做了一个功能,也就是订单会发送到我们公司来。我们会建一个time_site的key的集合,而且集合本身有去重的功能,而且我们可以很方便的通过set.Count功能来统计数量,当件被揽收以后,我们后台把这个件从集合中Remove掉。然后这个Set中存在的就是网点还没有揽收的件,这时候通过Count就会知道这个网点今天还有多少件没有揽收。实际使用中这个数量比较大,因为有几万个网点。

    Redis中布隆过滤器,去重的,面试的时候问的比较多。

    小经验分享:

    数据库中不合法的时间处理:判断时间中的年份是否大于2000年,如果小于2000就认为不合法;习惯大于小于号不习惯用等于号,这样可以处理很多意外的数据;

    Set的时候最好指定过期时间,防止有些需要删除的数据我们忘记删了;

    Redis异步尽量不用,因为Redis延迟本身很小,大概在100us-200us,再一个就是Redis本身是单线程的,异步任务切换的耗时比网络耗时还要大;

    List用法:物联网中数据上传,量比较大时,我们可以把这些数据先放在Redis的List中,比如说一秒钟1万条,然后再批量取出来然后批量插入数据库中。这时候要设置好key,可以前缀+时间,对已处理的List可以进行remove移除。

    2、压力测试

    接下来看第四个例子,我们直接做压力测试,代码如下:

    运行的结果如下图所示:

    测试就是进行get,set remove,累加等的操作。大家可以看到在我本机上轻轻松松的到了六十万,多线程的时候甚至到了一百多万。

    为什么会达到这么高的Ops呢?下面给大家说一下:

    • Bench会分根据线程数分多组进行添删改压力测试;

    • rand参数,是否随机产生key/value;

    • batch批大小,分批执行读写操作,借助GetAll/SetAll进行优化。

    3、Redis中NB的函数来提升性能

    上面的操作如果大家都掌握了就基本算Redis入门了,接下来进行进阶。如果能全然吃透,差不多就会比别人更胜一筹了。

    GetAll()与SetAll()

    GetAll:比方说我要取十个key,这个时候可以用getall。这时候Redis就执行了一次命令。比方说我要取10个key那么用get的话要取10次,如果用getall的话要用1次。1次getall时间大概是get的一点几倍,但是10次get的话就是10倍的时间,这个账你应该会算吧?强烈推荐大家用getall。

    setall跟getall相似,批量设置K-V。

    setall与getall性能很恐怖,官方公布的Ops也就10万左右,为什么我们的测试轻轻松松到五十万甚至上百万?因为我们就用了setall,getall。如果get,set两次以上,建议用getall,setall。

    Redis管道Pipeline

    比如执行10次命令会打包成一个包集体发过去执行,这里实现的方式是StartPipeline()开始,StopPipeline()结束中间的代码就会以管道的形式执行。

    这里推荐使用更强的武器,AutoPipeline自动管道属性。管道操作到一定数量时,自动提交,默认0。使用了AutoPipeline,就不需要StartPipeline,StopPipeline指定管道的开始结束了。

    Add与Replace

    • Add:Redis中没有这个Key就添加,有了就不要添加,返回false;

    • Replace:有则替换,还会返回原来的值,没有则不进行操作。

    Add跟Replace就是实现Redis分布式锁的关键。

    三、Redis使用技巧,经验分享

    在项目的Readme中,这里摘录下:

    1、特性

    在ZTO大数据实时计算广泛应用,200多个Redis实例稳定工作一年多,每天处理近1亿包裹数据,日均调用量80亿次;

    低延迟,Get/Set操作平均耗时200~600us(含往返网络通信);

    大吞吐,自带连接池,最大支持1000并发;

    高性能,支持二进制序列化(默认用的json,json很低效,转成二进制性能会提升很多)。

    2、Redis经验分享

    在Linux上多实例部署,实例个数等于处理器个数,各实例最大内存直接为本机物理内存,避免单个实例内存撑爆(比方说8核心处理器,那么就部署8个实例)。

    把海量数据(10亿+)根据key哈希(Crc16/Crc32)存放在多个实例上,读写性能成倍增长。

    采用二进制序列化,而非常见的Json序列化。

    合理设计每一对Key的Value大小,包括但不限于使用批量获取,原则是让每次网络包控制在1.4k字节附近,减少通信次数(实际经验几十k,几百k也是没问题的)。

    Redis客户端的Get/Set操作平均耗时200~600us(含往返网络通信),以此为参考评估网络环境和Redis客户端组件(达不到就看一下网络,序列化方式等等)。

    使用管道Pipeline合并一批命令。

    Redis的主要性能瓶颈是序列化、网络带宽和内存大小,滥用时处理器也会达到瓶颈。

    其它可查优化技巧。

    以上经验,源自于300多个实例4T以上空间一年多稳定工作的经验,并按照重要程度排了先后顺序,可根据场景需要酌情采用。

    3、缓存Redis的兄弟姐妹

    Redis实现ICache接口,它的孪生兄弟MemoryCache,内存缓存,千万级吞吐率。各应用强烈建议使用ICache接口编码设计,小数据时使用MemoryCache实现;数据增大(10万)以后,改用Redis实现,不需要修改业务代码。

    Java高级部落

    共享Java行业资讯,分享公司内部核心干货,中高Java开发级技术,关注我一起探索Java编程架构之路。

    展开全文
  • 为什么使用Redis pom.xml配置文件 代码片段展示 1.从mysql中查询到Telid和dateid,先保存到map集合中 2.向redis中存储电话号码和电话号码的id(date和dateid一样) 整体代码 表设计介绍 在本项目的MapReduce...

    目录

    表设计介绍

    为什么使用Redis

    pom.xml配置文件

    代码片段展示

    1.从mysql中查询到Telid和dateid,先保存到map集合中

    2.向redis中存储电话号码和电话号码的id(date和dateid一样)

    整体代码


    表设计介绍

    在本项目的MapReduce分析阶段之后的自定义outputformat阶段,将分析后的数据写入到MySQL中。在该项目的表设计中,为了提高mysql的存储效率,解决宽表和高表问题,我们使用了三张表来存储项目数据,分别是ct-user、ct-date、ct-call

    • ct-user用于存储用户电话号码和ID以及用户姓名
    • ct-date用于存放通话日期以及ID
    • ct-call用于存放分析后的数据,该表有五个字段,分别是id、telid、dateid、sumcall(总通话次数)、sumduration(总通话时长)

    为什么使用Redis

    在MapReduce阶段分析完成后,将分析的结果插入到MySQL数据库中,id为自增长,telid为用户表ct-user中的电话号码对应的id,而不是电话号码,dateid对应的是日期表ct-date表中通话日期对应的id,而不是通话日期。这就需要通过reduce方法处理后输出的key和value(key中包含了电话号码tel和通话时间date)来从mysql的ct-user表和ct-date表中取得对应的id号,然后插入到ct-call表中。考虑到每一次向MySQL插入数据都要从MySQL中查询一次telid和dateid,这样效率很低。因此考虑到使用Redis缓存来解决这个问题,将MySQL中的电话号码tel和id以及日期date和dateid先查询出来缓存到Redis中,这样每一次向MySQL中插入分析后的数据时直接从Redis缓存中取数据,而不用去查询MySQL数据库。使得性能得到提升。

    pom.xml配置文件

    由于在该模块需要操作Redis以及从MySQL中查询数据和插入数据,所以需要在pom.xml文件中引入redis依赖和mysql的驱动!

            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.9.0</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.18</version>
            </dependency>

    代码片段展示

    1.从mysql中查询到Telid和dateid,先保存到map集合中

    public static void main(String[] args) {
    
            //读取mysql中的数据
            //将两张表缓存到内存中
            Map<String,Integer> userMap = new HashMap<>();
            Map<String,Integer> dateMap = new HashMap<>();
    
            Connection connection = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try {
    
                connection = JDBCUtil.getConnection();
    
                String queryUserSql = "select id,tel from ct_user";
                pstat = connection.prepareStatement(queryUserSql);
                rs = pstat.executeQuery();
    
                while (rs.next()){
                    Integer id = rs.getInt(1);
                    String tel = rs.getString(2);
    
                    //将用户的Tel和id从数据库中取出,保存到map中,相当于加载到缓存中,方便后面做id映射
                    userMap.put(tel,id);
                }
                rs.close();
    
                //查询时间
                String queryDateSql = "select id,year,month,day from ct_date";
                pstat = connection.prepareStatement(queryDateSql);
                rs = pstat.executeQuery();
                while (rs.next()){
                    Integer id = rs.getInt(1);
                    String year = rs.getString(2);
                    String month = rs.getString(3);
                    //保证月份是两位数
                    if(month.length() == 1){
                        month = "0" + month;
                    }
                    String day = rs.getString(4);
                    if(day.length() == 1){
                        day = "0" + day;
                    }
    
                    //将用户的Tel和id从数据库中取出,保存到map中,相当于加载到缓存中,方便后面做id映射
                    dateMap.put(year + month + day,id);
                }

    2.向redis中存储电话号码和电话号码的id(date和dateid一样)

           //向redis中存储telid数据
           Jedis jedis = new Jedis("cMaster",6379);
            Iterator<String> keyIterator = userMap.keySet().iterator();
            while (keyIterator.hasNext()){
                String key = keyIterator.next();
                Integer value = userMap.get(key);       //通过电话号码取得id然后存放在redis中
                jedis.hset("ct_user",key,"" + value);
            }

    整体代码展示

    package com.wp.ct.cache;
    
    import com.wp.ct.common.util.JDBCUtil;
    import redis.clients.jedis.Jedis;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    /**
     * 使用redis做缓存:将MySQL中的数据查询出来,然后缓存到redis中
     * 启动缓存客户端,向redis中增加缓存数据
     */
    public class Bootstrap {
        public static void main(String[] args) {
    
            //读取mysql中的数据
            //将两张表缓存到内存中
            Map<String,Integer> userMap = new HashMap<>();
            Map<String,Integer> dateMap = new HashMap<>();
    
            Connection connection = null;
            PreparedStatement pstat = null;
            ResultSet rs = null;
            try {
    
                connection = JDBCUtil.getConnection();
    
                String queryUserSql = "select id,tel from ct_user";
                pstat = connection.prepareStatement(queryUserSql);
                rs = pstat.executeQuery();
    
                while (rs.next()){
                    Integer id = rs.getInt(1);
                    String tel = rs.getString(2);
    
                    //将用户的Tel和id从数据库中取出,保存到map中,相当于加载到缓存中,方便后面做id映射
                    userMap.put(tel,id);
                }
                rs.close();
    
                //查询时间
                String queryDateSql = "select id,year,month,day from ct_date";
                pstat = connection.prepareStatement(queryDateSql);
                rs = pstat.executeQuery();
                while (rs.next()){
                    Integer id = rs.getInt(1);
                    String year = rs.getString(2);
                    String month = rs.getString(3);
                    //保证月份是两位数
                    if(month.length() == 1){
                        month = "0" + month;
                    }
                    String day = rs.getString(4);
                    if(day.length() == 1){
                        day = "0" + day;
                    }
    
                    //将用户的Tel和id从数据库中取出,保存到map中,相当于加载到缓存中,方便后面做id映射
                    dateMap.put(year + month + day,id);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                if(rs != null){
                    try {
                        rs.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(pstat != null){
                    try {
                        pstat.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if (connection != null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            //向redis中存储telid数据
           Jedis jedis = new Jedis("cMaster",6379);
            Iterator<String> keyIterator = userMap.keySet().iterator();
            while (keyIterator.hasNext()){
                String key = keyIterator.next();
                Integer value = userMap.get(key);       //通过电话号码取得id然后存放在redis中
                jedis.hset("ct_user",key,"" + value);
            }
    
            //将时间和id缓存到redis中
            keyIterator = dateMap.keySet().iterator();
            while (keyIterator.hasNext()){
                String key = keyIterator.next();
                Integer value = dateMap.get(key);       //通过电话号码取得id然后存放在redis中
                jedis.hset("ct_date",key,"" + value);
            }
        }
    }
    

     

    展开全文
  • Java大数据-Redis

    2018-08-28 22:01:33
    Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的应用程序的完美解决方案。 Redis从它的许多竞争继承来的三个主要特点: ØRedis数据库完全在内存中,使用磁盘仅用于持久性。 Ø相比许多键值...

    Redis学习结构

     Redis基础

    Redis概述

    Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的应用程序的完美解决方案。

    Redis从它的许多竞争继承来的三个主要特点:

    ØRedis数据库完全在内存中,使用磁盘仅用于持久性。

    Ø相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。

    ØRedis可以将数据复制到任意数量的从服务器。

    Redis 优势

    Ø异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录

    Ø支持丰富的数据类型:String(字符串)、List(列表)、set(集合)、Sort Set(有序集合)、Hash(散列数据)

    Ø操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。

    Ø多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。

            Redis 部署

    参考:https://blog.csdn.net/CherrieZhang/article/details/77677516

            Redis 持久化

    两种持久化方案:RDB和AOF

     1)RDB方式按照一定的时间间隔对数据集创建基于时间点的快照

     2)AOF方式记录Server收到的写操作到日志文件,在Server重启时通过回放这些写操作来重建数据集。 

          该方式类似于MySQL中基于语句格式的binlog。当日志变大时Redis可在后台重写日志。

    •RDB持久化配置

    默认情况下,Redis保存数据集快照到磁盘,名为dump.rdb的二进制文件。可以设置让RedisN秒内至少有M次数据集改动时保存数据集,或者你也可以手动调用SAVE或者BGSAVE命令。 
    例如,这个配置会让
    Redis在每个60秒内至少有1000次键改动时自动转储数据集到磁盘   save 60 1000 

    •AOF持久化配置

     1)修改redis.config配置文件,找到appendonly默认是appendonly no。改成appendonly yes

     2)再找到appendfsync 。默认是 appendfsync everysec

                  appendfsync always  

                  #每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用  

    appendfsync everysec    

    #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐  

    appendfsync no    

    #完全依赖os性能最好,持久化没保证  

    Jedis

    Jedis是Java代码操控Redis的一个客户端工具。

    Jedis API:https://blog.csdn.net/zhangguanghui002/article/details/78770071

    Jedis池相关:

    package redis.other;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.JedisPoolConfig;
    
    /**
     * Describe: 请补充类描述
     */
    public class MyJedisPool {
        // jedis池
        public static JedisPool pool;
    
        // 静态代码初始化池配置
        static {
            //change "maxActive" -> "maxTotal" and "maxWait" -> "maxWaitMillis" in all examples
            JedisPoolConfig config = new JedisPoolConfig();
            //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
            config.setMaxIdle(5);
            //控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
            //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
            //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
            config.setMaxTotal(1000 * 100);
            //表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
            config.setMaxWaitMillis(5);
            config.setTestOnBorrow(true);
            config.setTestOnReturn(true);
            try {
                //如果你遇到 java.net.SocketTimeoutException: Read timed out exception的异常信息
                //请尝试在构造JedisPool的时候设置自己的超时值. JedisPool默认的超时时间是2秒(单位毫秒)
                pool = new JedisPool(config, "127.0.0.1", 6379, 20);
            } catch (Exception e) {
                throw new RuntimeException("redis 连接池初始化失败!");
            }
        }
    
        public static void main(String[] args) {
            // 从jedis池中获取一个jedis实例
            Jedis jedis = MyJedisPool.pool.getResource();
            // 添加key-value对象,如果key对象存在就覆盖该对象
            jedis.set("name", "maoxiangyi");
            jedis.set("company", "aaa");
            // 查取key的value值,如果key不存在返回null
            String name = jedis.get("name");
            String company = jedis.get("company");
            System.out.println(company + ":" + name);
            // 删除key-value对象,如果key不存在则忽略此操作
            jedis.del("name");
            // 判断key是否存在,不存在返回false存在返回true
            jedis.exists("name");
            //关闭jedis链接,自动回收
            jedis.close();
        }
    }
    

     

    String

    先讲个面试题吧:Redis对int类型数值进行加1操作如何实现?

    我们知道Redis数据类型中没有int的,解释Redis数字操作:https://blog.csdn.net/chengqiuming/article/details/79118084

    String类型基本操作:

    package redis.string;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.List;
    
    /**
     * Describe: 请补充类描述
     */
    public class StringMain {
    
        public static void main(String[] args) throws InterruptedException {
            //创建Jedis客户端
            Jedis jedis = new Jedis("127.0.0.1", 6379);
    
            //操作一个String字符串
            jedis.set("name", "liudehua"); //插入一个名字,叫做刘德华
            System.out.println(jedis.get("name")); //读取一个名字
    
            //对string类型数据进行增减,前提是kv对应的值是数字
            jedis.set("age", "17");//给用户刘德华设置年龄,17岁
            jedis.incr("age");//让用户刘德华年龄增加一岁
            System.out.println(jedis.get("age")); //打印结果 18
            jedis.decr("age");//让刘德华年轻一岁
            System.out.println(jedis.get("age"));//在18的基础上,减一岁,变回17
    
            //一次性插入多条数据 。为江湖大侠设置绝杀技能
            jedis.mset("AAA", "Mysql数据库的操作"
                    , "BBB", "熟悉LINXU操作系统"
                    , "CCC", "熟悉SSH、SSM框架及配置"
                    , "DDD", "熟悉Spring框架,mybatis框架,Spring IOC MVC的整合,Spring和Mybatis的整合");
            List<String> results = jedis.mget("AAA", "BBB", "CCC", "DDD");
            for (String value : results) {
                System.out.println(value);
        }
    
            //设置字段的自动过期
            jedis.setex("wumai", 10, "我们活在仙境中"); //让仙境保持10秒钟
            while (jedis.exists("wumai")) {
                System.out.println("真是天上人间呀!");
                Thread.sleep(1000);
            }
    
    
    
            System.out.println();
            //对已经存在的字段设置过期时间
            jedis.set("wumai", "我们活在仙境中");
            jedis.expire("wumai", 10); //让天上人间的感觉保持更长的时间
            while (jedis.exists("wumai")) {
                System.out.println("真是天上人间呀!");
                Thread.sleep(1000);
            }
    
        }
    }
    

    对象的保存:

    package redis.string;
    
    import com.google.gson.Gson;
    import org.junit.Test;
    import redis.clients.jedis.Jedis;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.util.Map;
    
    /**
     * Describe: 保存Product对象到redis中
     */
    public class ProductService {
    
        @Test
        public void saveProduct2Redis() throws Exception {
            //初始化刘德华的基本信息
            Person person = new Person("刘德华", 17);
            //将刘德华的信息保存到Redis中
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            //直接保存对象的toString方法,这种方法不反序列化对象
            jedis.set("user:liudehua:str", person.toString());
            System.out.println(jedis.get("user:liudehua:str"));
    
            //保存序列化之后的对象
            jedis.set("user:liudehua:obj".getBytes(), getBytesByProduct(person));
            byte[] productBytes = jedis.get("user:liudehua:obj".getBytes());
            Person pByte = getProductByBytes(productBytes);
            System.out.println(pByte.getName()+"  " +pByte.getAge());
    
            //保存Json化之后的对象
            jedis.set("user:liudehua:json", new Gson().toJson(person));
            String personJson = jedis.get("user:liudehua:json");
            Person pjson = new Gson().fromJson(personJson, Person.class);
            System.out.println(pjson.getName()+"  "+ pjson.getAge());
    
    
        }
    
        /**
         * 从字节数组中读取Java对象
         *
         * @param productBytes
         * @return
         * @throws Exception
         */
        public Person getProductByBytes(byte[] productBytes) throws Exception {
            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(productBytes);
            ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);
            return (Person) objectInputStream.readObject();
        }
    
        /**
         * 将对象转化成Byte数组
         *
         * @param product
         * @return
         * @throws Exception
         */
        public byte[] getBytesByProduct(Person product) throws Exception {
            ByteArrayOutputStream ba = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(ba);
            oos.writeObject(product);
            oos.flush();
            return ba.toByteArray();
        }
    }
    

    应用场景:String数据类型实现计数功能

    因为Redis都是原子性操作,可应用于多线程情景下实现计数功能。

    package redis.string;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Describe: 擂台比武
     */
    public class Counter {
        /**
         * 计算 武林大会 三个擂台的比武次数
         *
         * @param args
         */
        public static void main(String[] args) {
            //创建一个固定大小的线程池,3个擂台
            ExecutorService executorService = Executors.newFixedThreadPool(10);
            //擂台1:天龙八部
            executorService.submit(new Arena("biwu:totalNum","天龙八部"));
            //擂台2:神雕侠侣
            executorService.submit(new Arena("biwu:totalNum","神雕侠侣"));
            //擂台3:倚天屠龙记
            executorService.submit(new Arena("biwu:totalNum","倚天屠龙记"));
            //报幕人员,一秒统计一次总共比了多少场
            executorService.submit(new BaoMu("biwu:totalNum"));
        }
    }
    
    
    package redis.string;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.Random;
    
    /**
     * Describe: 擂台
     */
    public class Arena implements Runnable {
    
        private Random random = new Random();
        private String redisKey;
        private Jedis jedis;
        private String arenaName;
    
        public Arena(String redisKey, String arenaName) {
            this.redisKey = redisKey;
            this.arenaName = arenaName;
        }
    
        public void run() {
            jedis = new Jedis("127.0.0.1",6379);
            String[] daxias = new String[]{"郭靖", "黄蓉", "令狐冲", "杨过", "林冲",
                    "鲁智深", "小女龙", "虚竹", "独孤求败", "张三丰", "王重阳", "张无忌"
                    , "王重阳", "东方不败", "逍遥子", "乔峰", "虚竹", "段誉"
                    , "韦小宝", "王语嫣", "周芷若", "峨眉师太", "慕容复"};
            while (true) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int p1 = random.nextInt(daxias.length);
                int p2 = random.nextInt(daxias.length);
                while (p1 == p2) { //如果两个大侠出场名字一样,换一个人
                    p2 = random.nextInt(daxias.length);
                }
                System.out.println("在擂台" + arenaName + "上   " + daxias[p1] + " VS " + daxias[p2]);
                jedis.incr(redisKey);
            }
        }
    }
    
    
    
    package redis.string;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.concurrent.Callable;
    
    /**
     * Describe: 报幕人员
     */
    public class BaoMu implements Runnable {
        private Jedis jedis;
        private String redisKey;
    
        public BaoMu(String redisKey) {
            this.redisKey = redisKey;
        }
    
        public void run() {
            jedis = new Jedis("127.0.0.1",6379);
            while (true) {
                try {
                    Thread.sleep(1000);
                    System.out.println("===================当前总共比武次数为:" + jedis.get(redisKey));
                } catch (Exception e) {
                    System.out.println("擂台被损坏..."+e);
                }
            }
        }
    }
    

    Hash数据类型

     Hash基本操作,区别Redis的key和Hash的key不是同一个概念

    package redis.map;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * Describe: 请补充类描述
     */
    public class MapMain {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            jedis.del("daxia:jingzhongyue");
            //创建一个对象
            jedis.hset("daxia:jingzhongyue", "姓名", "不为人知");
            jedis.hset("daxia:jingzhongyue", "年龄", "18");
            jedis.hset("daxia:jingzhongyue", "技能", "杀人于无形");
    
            //打印对象
            Map<String, String> jingzhongyue = jedis.hgetAll("daxia:jingzhongyue");
            System.out.println("hgetAll  大侠的基本信息:");
            for (Map.Entry entry : jingzhongyue.entrySet()) {
                        System.out.println(entry.getKey() + ":-----------------" + entry.getValue());
        }
        System.out.println();
    
            //获取大侠的所有字段信息
            Set<String> fields = jedis.hkeys("daxia:jingzhongyue");
            System.out.println("hkeys  ");
            for (String field : fields) {
                System.out.print(field + "  ");
            }
            System.out.println();
            //获取大侠的所有值的信息
            List<String> values = jedis.hvals("daxia:jingzhongyue");
            System.out.println("hvals " );
            for (String value : values) {
                System.out.print(value + "  ");
            }
            System.out.println();
    
            //值获取大侠的年龄,进行研究
            String age = jedis.hget("daxia:jingzhongyue", "年龄");
            System.out.println("对大侠的年龄有质疑:" + age);
            //给大侠的年龄增加十岁
            jedis.hincrBy("daxia:jingzhongyue", "年龄", 10);
            System.out.println("经过验核,大侠的实际年龄为:" + jedis.hget("daxia:jingzhongyue", "年龄"));
            System.out.println();
    
            //删除大侠的姓名
            jedis.hdel("daxia:jingzhongyue", "姓名");
            for (Map.Entry entry : jedis.hgetAll("daxia:jingzhongyue").entrySet()) {
                System.out.println(entry.getKey() + ":" + entry.getValue());
            }
    
        }
    }
    

     应用场景:Hash数据类型实现购物车,一个购物车对应一个Map集合。

    package redis.map;
    
    import com.google.gson.Gson;
    import redis.clients.jedis.Jedis;
    import redis.string.StringMain;
    
    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * Describe: 购物车
     */
    public class Cart {
        private Jedis jedis;
    
        public Cart() {
            jedis = new Jedis("127.0.0.1", 6379);
        }
    
        public Cart(Jedis jedis) {
            this.jedis = jedis;
        }
    
        /**
         * 修改购物车中的商品
         *
         * @param userName  用户名
         * @param productId 商品编号
         * @param num       操作商品的数量
         */
        public void updateProduct2Cart(String userName, String productId, int num) {
            jedis.hincrBy("shop:cart:" + userName, productId, num);
        }
    
        /**
         * 获取用户购物车的商品信息
         *
         * @param userName
         * @return
         */
        public List<Product> getProductsByUserName(String userName) {
            List<Product> products = new ArrayList<Product>();
            Map<String, String> productMap = jedis.hgetAll("shop:cart:" + userName);
            if (productMap == null || productMap.size() == 0) {
                return products;
            }
            for (Map.Entry entry : productMap.entrySet()) {
                Product product = new Product();
                product.setId((String) entry.getKey());//获取用户购物车中商品的编号
                int num = Integer.parseInt((String) entry.getValue());//获取用户购物车中商品的数量
                product.setNum(num > 0 ? num : 0);//如果商品数量大于0,返回正常的值,如果商品小于0,初始化为0
                complementOtherField(product);//补全商品的其他信息
                products.add(product);
            }
            return products;
        }
    
        private void complementOtherField(Product product) {
            String productId = product.getId();
            String productJsonStr = jedis.get("shop:product:" + productId);
            Product productJson = (Product) new Gson().fromJson(productJsonStr, Product.class);
            if (productJson != null) {
                product.setName(productJson.getName());
                product.setPrice(productJson.getPrice());
            }
        }
    
        public static void main(String[] args) {
            //初始化商品的信息
            initData();
            //创建购物车对象
            Cart cart = new Cart();
            //创建用户
            String userName = "liudehua";
            //往用户购物车中添加商品
            cart.updateProduct2Cart(userName, "1645080454", 10);
            cart.updateProduct2Cart(userName, "1788744384", 1000);
            cart.updateProduct2Cart(userName, "1645139266", -1000);
            //打印当前用户的购物车信息
            List<Product> products = cart.getProductsByUserName(userName);
            for (Product product : products) {
                System.out.println(product);
            }
        }
    
        private static void initData() {
            System.out.println("========================初始化商品信息===========================");
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            //准备数据
            Product product1 = new Product("1645139266", "战地鳄2015秋冬新款马甲可脱卸帽休闲时尚无袖男士羽绒棉外套马甲", new BigDecimal("168"));
            Product product2 = new Product("1788744384", "天乐时 爸爸装加厚马甲秋冬装中年大码男士加绒马夹中老年坎肩老年人", new BigDecimal("40"));
            Product product3 = new Product("1645080454", "战地鳄2015秋冬新款马甲可脱卸帽休闲时尚无袖男士羽绒棉外套马甲", new BigDecimal("230"));
            //将数据写入到Redis
            jedis.set("shop:product:" + product1.getId(), new Gson().toJson(product1));
            jedis.set("shop:product:" + product2.getId(), new Gson().toJson(product2));
            jedis.set("shop:product:" + product3.getId(), new Gson().toJson(product3));
            //打印所有产品信息
            Set<String> allProductKeys = jedis.keys("shop:product:*"); //获取所有的商品信息
            for (String key : allProductKeys) {
                String json = jedis.get(key);
                Product product = new Gson().fromJson(json, Product.class);//从字符串中解析出对象
                System.out.println(product);
            }
            System.out.println("========================用户购物车信息如下===========================");
    
        }
    }
    
    
    
    package redis.map;
    
    import java.math.BigDecimal;
    
    /**
     * Describe:商品类
     */
    public class Product {
        private String id;//商品编号
        private String name;//商品名称
        private BigDecimal price;//商品价格
        private int num;//商品数量
    
        public Product() {
        }
    
        public Product(String id, String name, BigDecimal price) {
            this.id = id;
            this.name = name;
            this.price = price;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public BigDecimal getPrice() {
            return price;
        }
    
        public void setPrice(BigDecimal price) {
            this.price = price;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        @Override
        public String toString() {
            return "Product{" +
                    "id='" + id + '\'' +
                    ", name='" + name + '\'' +
                    ", price=" + price +
                    ", num=" + num +
                    '}';
        }
    }
    

    List

     List基本操作:List左右端均可以操作,相当于双向队列。

    package redis.list;
    
    import redis.clients.jedis.BinaryClient;
    import redis.clients.jedis.Jedis;
    
    import java.util.List;
    
    /**
     * 天龙八部外传-麦当劳风云
     */
    public class ListMain {
        public static void main(String[] args) {
            //创建一个Redis的客户端
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            jedis.del("柜台1");
    
            //鸠摩智,虚竹,段誉,乔峰 排队买肯德基
            jedis.lpush("柜台1", "乔峰", "段誉", "虚竹", "鸠摩智");
            for (String name : jedis.lrange("柜台1", 0, -1)) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情:新来一个人 王语嫣,插队,到第一名。
            jedis.rpush("柜台1", "王语嫣");
            List<String> list = jedis.lrange("柜台1", 0, -1);
            for (String name : list) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情:鸠摩智很不高兴,正好慕容复来了,说:慕容兄,你插我前面
            jedis.linsert("柜台1", BinaryClient.LIST_POSITION.AFTER, "鸠摩智", "慕容复");
            List<String> list1 = jedis.lrange("柜台1", 0, -1);
            for (String name : list1) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情:看到慕容复插队大家很生气,正好阿紫和游坦之。让阿紫和游坦之依次插到虚竹的后面
            jedis.linsert("柜台1", BinaryClient.LIST_POSITION.BEFORE, "虚竹", "阿紫");
            jedis.linsert("柜台1", BinaryClient.LIST_POSITION.BEFORE, "阿紫", "游坦之");
            List<String> list2 = jedis.lrange("柜台1", 0, -1);
            for (String name : list2) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情:插队不文明,为了遏制这种不文明的现象,大决决定打一架。  鸠摩智被打跑了。
            jedis.lpop("柜台1");
            for (String name : jedis.lrange("柜台1", 0, -1)) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情:慕容复一看情况不好,以表哥的身份忽悠王语嫣,把王语嫣打伤。
            jedis.rpop("柜台1");
            for (String name : jedis.lrange("柜台1", 0, -1)) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情:在大家打架的时候,我偷偷插队,买了肯德基。
            jedis.rpush("柜台1", "井中月");
            for (String name : jedis.lrange("柜台1", 0, -1)) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情;等我买了肯德基,慕容复被打跑了
            jedis.lpop("柜台1");
            for (String name : jedis.lrange("柜台1", 0, -1)) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
            //剧情:星宿老怪 突然来了,把 阿紫和游坦之同时弄走了。
            String result = jedis.ltrim("柜台1", 2, 5);
            if ("OK".equals(result)) {
                for (String name : jedis.lrange("柜台1", 0, -1)) {
                    System.out.print(name + "  ");
                }
            }
            System.out.println("");
    
            //剧情:这时候,乔峰三人发现了我,与我大战三百回合,我全身而退
            String res = jedis.ltrim("柜台1", 0, 2);
            if ("OK".equals(res)) {
                for (String name : jedis.lrange("柜台1", 0, -1)) {
                    System.out.print(name + "  ");
                }
            }
    
        }
    }
    

    应用场景:网络爬虫

    package redis.list;
    
    import org.jsoup.Jsoup;
    import org.jsoup.helper.StringUtil;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    import redis.clients.jedis.Jedis;
    
    import java.util.Date;
    import java.util.List;
    
    public class Crawler {
        //定义需要爬取的url list
        private static final String redisUrlsWillKey = "crawler:urls:will";
        //如果需要去重的话,可以使用set保存已经爬起过的url
    
        public static void main(String[] args) throws Exception {
            //准备Url
            String startUrl = "https://www.huxiu.com/article/259690.html";
            String domain = "http://www.huxiu.com/";
            //获取文章Url
            getUrls(startUrl, domain);
            //处理url,下载文章的内容并打印
            parserUrl();
        }
    
        private static void parserUrl() throws Exception {
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            //从右边弹出一个url
            while (true) {
                String url = jedis.rpop(redisUrlsWillKey);
                try {
                    Article article = parser(url);
                    System.out.println(article);
                } catch (Exception e) {
    //                jedis.lpush(redisUrlsWillKey, url);
                }
            }
        }
    
        private static Article parser(String url) throws Exception {
            Document articleDocument = Jsoup.connect(url).get();
            Article article = new Article();
            // 封装作者的信息
            Elements author = articleDocument
                    .getElementsByClass("author-name");
            article.setAuthor(StringUtil.isBlank(author.text()) ? "jingzhongyue"
                    : author.text());
            // 抽取文章日期
            Elements date = articleDocument
                    .getElementsByClass("article-time");
            article.setDate(StringUtil.isBlank(date.text()) ? new Date()
                    : DateUtil.getDate(date.text()));
            // 抽取文章标题
            Elements title = articleDocument.getElementsByTag("title");
            article.setTitle(title.text());
            // 抽取文章编号
            // http://www.huxiu.com/article/124698/1.html
            String id = url.substring(29);
            int index = id.indexOf("/");
            id = id.substring(0, index);
            article.setId(id);
            // 抽取文章正文
            StringBuffer stringBuffer = new StringBuffer();
            Elements contents = articleDocument
                    .getElementsByAttribute("id");
            for (Element element : contents) {
                String idTag = element.attr("id");
                if ("article_content".equals(idTag)) {
                    Elements childs = element.children();
                    Elements pElements = childs.tagName("p");
                    for (Element element2 : pElements) {
                        stringBuffer.append(element2.text());
                    }
                }
            }
            return article;
        }
    
        private static void getUrls(String startUrl, String domain) throws Exception {
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            Document document = Jsoup.connect(startUrl).get();
            Elements elements = document.getElementsByAttribute("href");
            for (Element element : elements) {
                String endUrl = element.attr("href");
                if (endUrl.contains("article")) {
                    String url = domain + endUrl;
                    System.out.println(url);
                    jedis.lpush(redisUrlsWillKey, url);
                }
            }
        }
    
    }
    

    Set

    Set基本操作:无序、无重复元素 

    package redis.set;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.Set;
    
    /**
     * Describe: 请补充类描述
     */
    public class SetMain {
    
        public static void main(String[] args) {
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            //河南武林人物登记表---杜绝冒名顶替的情况
            String[] daxias = new String[]{"郭靖", "黄蓉", "令狐冲", "杨过", "林冲",
                    "鲁智深", "小女龙", "虚竹", "独孤求败", "张三丰", "王重阳", "张无忌"
                    , "王重阳", "东方不败", "逍遥子", "乔峰", "虚竹", "段誉"
                    , "韦小宝", "王语嫣", "周芷若", "峨眉师太", "慕容复", "郭靖", "乔峰", "王重阳"};
    
            //创建并设置一个set的值
            jedis.sadd("biwu:dengji", daxias);
            //获取一个set中所有的元素
            Set<String> daxiaSet = jedis.smembers("biwu:dengji");
            for (String name : daxiaSet) {
                System.out.print(name + " ");  //set集合的特点:无序、无重复元素
            }
            System.out.println();
    
    
            //判断一个成员是否属于某条指定的set数据
            boolean isComing = jedis.sismember("biwu:dengji", "井中月"); //判断大侠井中月是否到来
            if (!isComing) {
                System.out.println("大侠 井中月尚未登记.");
            }
            //计算一个set中有多少元素
            long totalNum = jedis.scard("biwu:dengji");
            System.out.println("有" + totalNum + " 位大侠已经登记了!");
            System.out.println();
    
    
    
            //大侠井中月没有来,是因为报名参与另外一个会议 国际武林大会
            String[] daxiaArr = new String[]{"王语嫣", "周芷若", "峨眉师太", "慕容复","郭靖", "乔峰", "井中月"};
            jedis.sadd("guoji:dengji", daxiaArr); //国际武林大会登记表
            Set<String> xindaxias = jedis.smembers("guoji:dengji");
            for (String name : xindaxias) {
                System.out.print(name + "--- ");  //集合的特点:无序、无重复元素
            }
            System.out.println();
    
    
            //计算两个Set之间的交集
            Set<String> users = jedis.sinter("biwu:dengji", "guoji:dengji");
            for (String name : users) {
                System.out.print(name + " ");
            }
            System.out.println();
    
    
            //计算两个Set之间的并集
            users = jedis.sunion("biwu:dengji", "guoji:dengji");
            for (String name : users) {
                System.out.print(name + " ");
            }
            System.out.println();
            System.out.println("井中月出来了");
    
    
            //计算两个集合的差集
            users = jedis.sdiff("biwu:dengji", "guoji:dengji");
            for (String name : users) {
                System.out.print(name + " ");
            }
            System.out.println();
    
            System.out.println();
            //将两个集合计算出来的差集保存起来,升级为超级Vip
            jedis.sdiffstore("vipdaxia","biwu:dengji", "guoji:dengji");
            for (String name : jedis.smembers("vipdaxia")) {
                System.out.print(name + " ");
            }
        }
    }
    

    应用场景:通过对两个集合的操作计算订单浏览、下单、支付等转化率

    package redis.set;
    
    import redis.clients.jedis.Jedis;
    
    import java.text.DecimalFormat;
    import java.text.NumberFormat;
    import java.util.Set;
    
    /**
     * Describe: 请补充类描述
     */
    public class Transform {
    
        public static void main(String[] args) {
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            //浏览某商品的用户
            jedis.sadd("viewUsers", "郭靖", "黄蓉", "令狐冲", "杨过", "林冲",
                    "鲁智深", "小女龙", "虚竹", "独孤求败", "张三丰", "王重阳", "张无忌"
                    , "王重阳", "东方不败", "逍遥子", "乔峰", "虚竹", "段誉");
    
            //下单用户
            jedis.sadd("orderUsers", "郭靖", "黄蓉", "令狐冲", "杨过", "林冲",
                    "鲁智深", "小女龙", "虚竹", "独孤求败", "乔峰", "虚竹", "段誉");
            //支付用户
            jedis.sadd("paymentUsers", "郭靖", "黄蓉", "令狐冲", "杨过", "独孤求败", "段誉");
    
            //浏览过商品的用户,有哪些下单了。
            jedis.sinterstore("view2order", "viewUsers", "orderUsers"); //求两个集合的交集
    
    
            //计算浏览某商品的用户数量 和 既浏览又下单的用户的数量
            double viewUserNum = jedis.scard("viewUsers");
            double orderUserNum = jedis.scard("view2order");
            NumberFormat formatter = new DecimalFormat("0.00");
            Double x = new Double(orderUserNum / viewUserNum);
            System.out.print("订单" + orderUserNum + "/浏览" + viewUserNum + "转化:" + formatter.format(x) + "     他们是:");
            for (String name : jedis.smembers("view2order")) {
                System.out.print(name + "  ");
            }
            System.out.println();
    
    
            //浏览并且下单的用户,最终支付的转化
            jedis.sinterstore("order2Payment", "view2order", "paymentUsers"); //求两个集合的交集
            double paymentUserNum = jedis.scard("paymentUsers");
            x = new Double(paymentUserNum / orderUserNum);
            System.out.print("支付" + paymentUserNum + "/订单" + orderUserNum + "转化:" + formatter.format(x) + "     他们是:");
            for (String name : jedis.smembers("order2Payment")) {
                System.out.print(name + "  ");
            }
            System.out.println();
            //浏览并最终支付的用户的转化
            x = new Double(paymentUserNum / viewUserNum);
            System.out.print("支付" + paymentUserNum + "/浏览" + viewUserNum + "转化:" + formatter.format(x)+"    他们是:");
            for (String name : jedis.smembers("order2Payment")) {
                System.out.print(name + "  ");
            }
            System.out.println();
        }
    }
    

     Sort Set

     Sort Set基本操作

    package redis.sortSet;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.Set;
    
    /**
     * Describe: 请补充类描述
     */
    public class SortMain {
    
        public static void main(String[] args) {
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            //往redis库中插入一条sortedset数据
            jedis.zadd("比武成绩", 10, "乔峰");
            jedis.zadd("比武成绩", 5, "王重阳");
            jedis.zadd("比武成绩", 7, "虚竹");
            jedis.zadd("比武成绩", 2, "王语嫣");
            jedis.zadd("比武成绩", 5, "段誉");
            jedis.zadd("比武成绩", 4, "峨眉师太");
            jedis.zadd("比武成绩", 20, "张三丰");
            //获取sortSet中所有的元素
            Set<String> names = jedis.zrange("比武成绩", 0, -1);
            for (String name : names) {
                System.out.println(name + "        排名: "
                        //打印用户升序排行
                        + jedis.zrank("比武成绩", name) + "           赢的场次: "
                        //打印用户的比武成绩
                        + jedis.zscore("比武成绩", name));
            }
            System.out.println("==============================");
    
            names = jedis.zrevrange("比武成绩", 0, -1);
            for (String name : names) {
                System.out.println(name + "         "
                        + jedis.zrevrank("比武成绩", name) + "            "
                        + jedis.zscore("比武成绩", name));
            }
            System.out.println("==============================");
    
            //修改用户的分数
            jedis.zincrby("比武成绩",100,"王语嫣");
            names = jedis.zrevrange("比武成绩", 0, -1);
            for (String name : names) {
                System.out.println(name + "         "
                        + jedis.zrevrank("比武成绩", name) + "            "
                        + jedis.zscore("比武成绩", name));
            }
        }
    }
    

    应用场景:天猫订单量和销售总额动态排行榜

    package redis.sortSet;
    
    import redis.clients.jedis.Jedis;
    
    import java.util.Random;
    import java.util.Set;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Describe: 请补充类描述
     */
    public class Bang {
    
        public static void main(String[] args) {
            //创建线程池
            ExecutorService executorService = Executors.newFixedThreadPool(10);
            //创建销售线程-销售商品
            executorService.submit(new Sale());
            executorService.submit(new Sale());
            //创建报表线程-周期型计算排行榜
            executorService.submit(new BangView());
        }
    }
    
    class Sale implements Runnable {
        //店铺销售排行榜
        private static final String amountBang = "tmall:amountBang";
        //店铺订单排行榜
        private static final String orderBang = "tmall:orderBang";
        //店铺名称
        private static final String[] shops = new String[]{"小米", "华为", "魅族", "苹果", "联想", "奇酷", "中兴", "一加", "oppo"};
        //Redis客户端
        private Jedis jedis = new Jedis("127.0.0.1", 6379);
        //随机获取店铺
        private Random random = new Random();
        //随机计算价格
        private Random priceRandom = new Random();
    
        public void run() {
            while (true) {
                try {
                    int shopIndex = random.nextInt(shops.length);
                    jedis.zincrby(amountBang, priceRandom.nextInt(2500), shops[shopIndex]);
                    jedis.zincrby(orderBang, 1, shops[shopIndex]);
    
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println(e);
                }
            }
        }
    
    }
    
    class BangView implements Runnable {
        //店铺销售排行榜
        private static final String amountBang = "tmall:amountBang";
        //店铺订单排行榜
        private static final String orderBang = "tmall:orderBang";
        //Redis客户端
        private Jedis jedis = new Jedis("127.0.0.1", 6379);
    
        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                    System.out.println("==============店铺销售额排行==============================");
                    Set<String> names = jedis.zrevrange(amountBang, 0, 4);
                    for (String name : names) {
                        System.out.println(name + "         "
                                + jedis.zrevrank(amountBang, name) + "            "
                                + jedis.zscore(amountBang, name));
                    }
                    System.out.println("==============店铺订单量排行==============================");
                    names = jedis.zrevrange(orderBang, 0, 1);
                    for (String name : names) {
                        System.out.println(name + "         "
                                + jedis.zrevrank(orderBang, name) + "            "
                                + jedis.zscore(orderBang, name));
                    }
    
                    System.out.println();
                    System.out.println();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
    

     

    展开全文
  • Redis集合:集合是什么,就是一堆确定的数据放在一起,数学上集合有交集、并集的概念,这个就可以用来做大数据的筛选功能。 以商品为例,假如商品有颜色和分类、价格区间等属性。 给所有统一颜色的商品放一个集合...
  • 本文根据李猛老师在〖deeplus直播第220期〗线上分享演讲内容整理而成。(文末有获取本期PPT&回放的途径,不要错过)李猛数据技术专家Elastic-Stack产品深度用户,...
  • redis常用命令大全1、常用场景2、常用命令2.1 key的常用命令2.2 String的常用命令2.3 List的常用命令2.4 Set的常用命令2.5 Sort Set的常用命令2.6 Hash的常用命令3、例程 1、常用场景 2、常用命令 基本类型:...
  • 1 大数据处理的常用方法 前面在我的另一篇文章中《大数据采集、清洗、处理:使用MapReduce进行离线数据分析完整案例》中已经有提及到,这里依然给出下面的图示: 前面给出的那篇文章是基于MapReduce的离线数据...
  • 大数据-Redis

    2019-08-10 16:29:31
    Redis Redis和Memcached的区别 (1)持久化 Redis可以做缓存,也可以做存储,支持ADF和RDB两种持久化方式;Memcached只能缓存数据 (2)数据结构 Redis有丰富的数据类型:字符串、链表,Hash、集合,有序集合;...
  • Redis面试专题及答案 什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免? 使用过 Redis 做异步队列么,你是怎么用的?有什么缺点? 使用过 Redis 分布式锁么,它是怎么实现的? 上述 Redis 分布式锁的缺点 ...
  • Redis持久化是有两种方式:RDB和AOF 对这两种方式的官方文档的翻译请看: http://latteye.com/2011/11/redis-persistence.html RDB就是快照存储,比如“每1个小时对redis进行快照存储”。那么, save这...
  • 评: 前几天微博发生了一起大的系统故障,很多技术的朋友都比较关心,其中的原因不会超出James Hamilton在On Designing and Deploying Internet-Scale Service(1)概括的那几个范围,James第一条经验“Design ....
  • 1.大数据处理的常用方法 大数据处理目前比较流行的是两种方法,一种是离线处理,一种是在线处理,基本处理架构如下: 在互联网应用中,不管是哪一种处理方式,其基本的数据来源都是日志数据,例如对于web应用来说...
  • Redis零、 目录 高并发思路 电商网站中缓存数据库的设计 缓存介绍 按照redis redis常用命令 redis其他数据结构 数据分布式存储 Jedis客户端 哈希一致性 补充 一、 高并发思路 技术: tomcat集群+ nginx 理论上引入...
  • redis 使用Jedis 控制操作 2. 使用keys进行模糊查询 public static Set<String> redisKeys(String pattern) { Set<String> keys = new HashSet<>(); //获取所有连接池节点 Map<String...
  • 问题导读: 1. 需求背景是什么? 2. 存储何种数据?...5. 解决方案有哪些? 6. md5散列桶的方法需要注意哪些问题? 7. 测试结果是什么? 解决方案: 1 需求背景 该应用场景为 DMP(Data...
  • 我们可以对系统存储使用的数据以两种角度分类,一种是按数据的大小划分,分成大数据和小数据,另一种是按数据的冷热程度划分,分成冷数据和热数据,热数据是指读或写比较频繁的数据,反之则是冷数据。  可以举一些...
  • 总结了好久,终于到了我最喜欢的redis部分,在这个阶段就让我们好好的了解一下这个强大的工具~ 一、redis介绍 redis是一个开源的,基于内存存储的数据结构服务器,可以被用作数据库,高速缓存和消息队列。它可以...
  • Redis(二)零 、 目录 将缓存引入电商项目 主从复制 哨兵模式 集群容忍度 CAP理论 十、 将缓存引入电商项目 使用Spring框架维护Jedis池对象引入一个配置文件 application-redis.config xmlns:context="http://ww
1 2 3 4 5 ... 20
收藏数 28,137
精华内容 11,254
关键字:

redis解决大数据