Java大数据-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.youkuaiyun.com/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.youkuaiyun.com/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.youkuaiyun.com/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();
            }
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值