1 Redis 介绍

1.1 概述

  • Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的应用程序的完美解决方案。
  • Redis数据库完全在内存中,使用磁盘仅用于持久性。
  • 相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。
  • Redis可以将数据复制到任意数量的从服务器。

1.2 优势

  • 异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录。
  • 支持丰富的数据类型:Redis支持字符串、列表、集合、有序集合散列数据类型。
  • 操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。
  • 多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。

2 持久化

2.1 两种持久化方案 RDB和AOF

  1. RDB方式按照一定的时间间隔对数据集创建基于时间点的快照
  2. AOF方式记录Server收到的写操作到日志文件,在Server重启时通过回放这些写操作来重建数据集。 该方式类似于MySQL中基于语句格式的binlog。当日志变大时Redis可在后台重写日志。

2.2 AOF持久化配置

  1. 修改redis.config配置文件,找到appendonly。默认是appendonly no。改成appendonly yes
  2. 再找到appendfsync 。默认是 appendfsync everysec,appendfsync always
  • 每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用appendfsync everysec
  • 每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐 appendfsync no
  • 完全依赖os,性能最好,持久化没保证

2.3 RDB持久化配置

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

2 window 上安装redis

安装参考redis安装

2.1 测试安装

先在服务里停止 Redis

hdel redis 最多多少field redis支持多大的数据量_redis

切换到 redis 安装的根目录,redis-server.exe redis.windows.conf

hdel redis 最多多少field redis支持多大的数据量_Java_02


hdel redis 最多多少field redis支持多大的数据量_redis String类型_03

3 新建 redis maven 工程

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tzb.cn</groupId>
    <artifactId>myredis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.3.1</version>
        </dependency>
    </dependencies>

</project>

3.1 String 测试

3.1.1 案例1

package mystring;

import redis.clients.jedis.Jedis;

import java.util.List;

public class StringMain {

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

        jedis.set("name","Mike");
        System.out.println(jedis.get("name"));

        /*
        * 对 string 类型数据进行增减,前提是kv 对应的值是数字
        * */
        jedis.set("age","25");//给用户 Mike设置年龄
        jedis.incr("age");//让 Mike的年龄增加一岁
        System.out.println(jedis.get("age"));

        /*
        * 一次性插入多条数据
        * */
        jedis.mset("AAA","A-金樽清酒斗十千",
                "BBB","B-玉盘珍羞直万钱",
                "CCC","C-停杯投箸不能食",
                "DDD","D-拔剑四顾心茫然");
        List<String> results=jedis.mget("AAA","BBB","CCC","DDD");
        for(String value:results){
            System.out.println(value);
        }

        /*
        * 设置字段的自动过期
        * */
        jedis.setex("tangshi",10,"直挂云帆济沧海"); // 这句古诗保持10秒钟
        while(jedis.exists("tangshi")){
            System.out.println("云帆济沧海");
            Thread.sleep(1000);
        }

        System.out.println();

        /*
        * 对已经存在的字段设置过期时间
        * */
        jedis.set("tangshi","直挂云帆济沧海");
        jedis.expire("tangshi",10);
        while(jedis.exists("tangshi")){
            System.out.println("云帆济沧海");
            Thread.sleep(1000);
        }

    }
}


package mystring;

import redis.clients.jedis.Jedis;

import java.util.List;

public class StringMain {

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

        jedis.set("name","Mike");
        System.out.println(jedis.get("name"));

        /*
        * 对 string 类型数据进行增减,前提是kv 对应的值是数字
        * */
        jedis.set("age","25");//给用户 Mike设置年龄
        jedis.incr("age");//让 Mike的年龄增加一岁
        System.out.println(jedis.get("age"));

        /*
        * 一次性插入多条数据
        * */
        jedis.mset("AAA","A-金樽清酒斗十千",
                "BBB","B-玉盘珍羞直万钱",
                "CCC","C-停杯投箸不能食",
                "DDD","D-拔剑四顾心茫然");
        List<String> results=jedis.mget("AAA","BBB","CCC","DDD");
        for(String value:results){
            System.out.println(value);
        }

        /*
        * 设置字段的自动过期
        * */
        jedis.setex("tangshi",10,"直挂云帆济沧海"); // 这句古诗保持10秒钟
        while(jedis.exists("tangshi")){
            System.out.println("云帆济沧海");
            Thread.sleep(1000);
        }

        System.out.println();

        /*
        * 对已经存在的字段设置过期时间
        * */
        jedis.set("tangshi","直挂云帆济沧海");
        jedis.expire("tangshi",10);
        while(jedis.exists("tangshi")){
            System.out.println("云帆济沧海");
            Thread.sleep(1000);
        }

    }
}
D:\programs\Java\jdk1.8.0_181\bin\java.exe "-javaagent:D:\programs\JetBrains\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar=55441:D:\programs\JetBrains\IntelliJ IDEA 2018.2.4\bin" -Dfile.encoding=UTF-8 -classpath D:\programs\Java\jdk1.8.0_181\jre\lib\charsets.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\deploy.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\javaws.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\jce.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\jfr.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\jsse.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\management-agent.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\plugin.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\resources.jar;D:\programs\Java\jdk1.8.0_181\jre\lib\rt.jar;D:\Data\JavaProject\myredis\target\classes;C:\Users\tzb\.m2\repository\redis\clients\jedis\2.8.2\jedis-2.8.2.jar;C:\Users\tzb\.m2\repository\org\apache\commons\commons-pool2\2.4.2\commons-pool2-2.4.2.jar mystring.StringMain
Mike
26
A-金樽清酒斗十千
B-玉盘珍羞直万钱
C-停杯投箸不能食
D-拔剑四顾心茫然
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海

云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海
云帆济沧海

Process finished with exit code 0

3.1.2 案例2

package mystring;


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
* 计算三个擂台的比武次数
* */
public class Counter {
    public static void main(String[] args){

      /*
      * 创建一个固定大小的线程池,3个擂台
      * */
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        /*
        * 擂台1,2,3
        * */
        executorService.submit(new Arena("PK:totalNum:","少林寺"));
        executorService.submit(new Arena("PK:totalNum:","武当派"));
        executorService.submit(new Arena("PK:totalNum:","峨眉派"));

        /*
        * 报幕人员
        * */
        executorService.submit(new BaoMu("PK:totalNum"));


    }
}


package mystring;


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
* 计算三个擂台的比武次数
* */
public class Counter {
    public static void main(String[] args){

      /*
      * 创建一个固定大小的线程池,3个擂台
      * */
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        /*
        * 擂台1,2,3
        * */
        executorService.submit(new Arena("PK:totalNum:","少林寺"));
        executorService.submit(new Arena("PK:totalNum:","武当派"));
        executorService.submit(new Arena("PK:totalNum:","峨眉派"));

        /*
        * 报幕人员
        * */
        executorService.submit(new BaoMu("PK:totalNum"));


    }
}
package mystring;


import redis.clients.jedis.Jedis;

import java.util.Random;

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", 6397);
        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 mystring;


import redis.clients.jedis.Jedis;

import java.util.Random;

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", 6397);
        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 mystring;

import redis.clients.jedis.Jedis;


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 (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}


package mystring;

import redis.clients.jedis.Jedis;


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 (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

3.1.3 案例3

package mystring;

import com.google.gson.Gson;
import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.io.*;

public class PruductService {

    @Test
    public void saveProduct2Redis() throws Exception{

        Person person =new Person("Mike",25);

        Jedis jedis=new Jedis("127.0.0.1",6379);

        //直接保存对象的toString方法,这种方式不反序列化对象
        jedis.set("user:Mike:str",person.toString());
        System.out.println(jedis.get("user:Mike:str"));

        //保存序列化后的对象
        jedis.set("user:Mike:obj".getBytes(),getBytesByProduct(person));
        byte[] productBytes=jedis.get("user:Mike:obj".getBytes());
        Person pByte=getProductByBytes(productBytes);
        System.out.println(pByte.getName()+"  "+pByte.getAge());

        //保存 Json 化之后的对象
        jedis.set("user:Mike:json",new Gson().toJson(person));
        String personJson=jedis.get("user:Mike:json");
        Person pjson=new Gson().fromJson(personJson,Person.class);
        System.out.println(pjson.getName()+" "+pjson.getAge());

    }

    /*
    * 从字节数组中读取对象
    * */
    public Person getProductByBytes(byte[] productBytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(productBytes);
        ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
        return (Person)objectInputStream.readObject();
    }

    /*
    *
    * 把对象转换为 Byte 数组
    * */
    public byte[] getBytesByProduct(Person product) throws IOException {
        ByteArrayOutputStream ba=new ByteArrayOutputStream();
        ObjectOutputStream oos= new ObjectOutputStream(ba);
        oos.writeObject(product);
        oos.flush();
        return ba.toByteArray();
    }


}


package mystring;

import com.google.gson.Gson;
import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.io.*;

public class PruductService {

    @Test
    public void saveProduct2Redis() throws Exception{

        Person person =new Person("Mike",25);

        Jedis jedis=new Jedis("127.0.0.1",6379);

        //直接保存对象的toString方法,这种方式不反序列化对象
        jedis.set("user:Mike:str",person.toString());
        System.out.println(jedis.get("user:Mike:str"));

        //保存序列化后的对象
        jedis.set("user:Mike:obj".getBytes(),getBytesByProduct(person));
        byte[] productBytes=jedis.get("user:Mike:obj".getBytes());
        Person pByte=getProductByBytes(productBytes);
        System.out.println(pByte.getName()+"  "+pByte.getAge());

        //保存 Json 化之后的对象
        jedis.set("user:Mike:json",new Gson().toJson(person));
        String personJson=jedis.get("user:Mike:json");
        Person pjson=new Gson().fromJson(personJson,Person.class);
        System.out.println(pjson.getName()+" "+pjson.getAge());

    }

    /*
    * 从字节数组中读取对象
    * */
    public Person getProductByBytes(byte[] productBytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(productBytes);
        ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
        return (Person)objectInputStream.readObject();
    }

    /*
    *
    * 把对象转换为 Byte 数组
    * */
    public byte[] getBytesByProduct(Person product) throws IOException {
        ByteArrayOutputStream ba=new ByteArrayOutputStream();
        ObjectOutputStream oos= new ObjectOutputStream(ba);
        oos.writeObject(product);
        oos.flush();
        return ba.toByteArray();
    }


}