工程目录

// pom.xml
<dependencies>

    <!--    1、 Jedis-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>
    <!--    2、 Junit测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--    3、 Lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.10</version>
        <scope>provided</scope>
    </dependency>


    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>


    <!-- 4. 导入spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.10.RELEASE</version>
    </dependency>


    <!--mvc-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.10.RELEASE</version>
    </dependency>


    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.10.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

// User.java
@Data
@AllArgsConstructor
@NoArgsConstructor

public class User implements Serializable {

private String username;

private String password;

}
基本用法

@Test

public void t1() {


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


    String set = jedis.set("name","zs");
    // "ok"
    System.out.println(set);


    Long lpush = jedis.lpush("list", "a", "b", "c");
    // 1
    System.out.println(lpush);


    // 设置值的同时指定生存时间
    String setex = jedis.setex("sex", 100, "女");
    // "ok"
    System.out.println(setex);


    jedis.close();
}


@Test
public void t2() {


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


    String result = jedis.get("name");
    // zs
    System.out.println(result);


    List<String> list = jedis.lrange("list", 0, -1);


    for (String s : list) {
        // c b a
        System.out.println(s);
    }


    // 23
    System.out.println(jedis.ttl("sex"));


    jedis.close();
}

连接池的使用

@Test

public void t3() {


    // 数据库连接池配置
    JedisPoolConfig config = new JedisPoolConfig();
    // 空闲数
    config.setMaxIdle(10);
    config.setMinIdle(5);
    // 最大连接数
    config.setMaxTotal(20);
    // 超时时间
    config.setMaxWaitMillis(3000);


    // 数据库连接池
    JedisPool jedisPool = new JedisPool(config,"10.36.144.110", 6379);
    Jedis jedis = jedisPool.getResource();
    String age = jedis.set("age", "13");
    // "ok"
    System.out.println(age);


    // 关闭的数据库会进入回收池
    jedis.close();
}

抽取公共类

封装set、get方法,并且序列化对象。

// RedisUtil.java

public class RedisUtil {

private static JedisPool pool;


static {
    JedisPoolConfig config = new JedisPoolConfig();
    config.setMaxIdle(10);
    config.setMinIdle(5);
    config.setMaxTotal(20);
    config.setMaxWaitMillis(3000);
    pool = new JedisPool(config,"10.36.144.110", 6379);
}


public static Jedis getJedis() {
    return pool.getResource();
}


public static void close(Jedis jedis) {
    jedis.close();
}


public static String set(String key, String value) {
    Jedis jedis = getJedis();
    String result = jedis.set(key, value);
    close(jedis);
    return result;
}


public static String get(String key) {
    Jedis jedis = getJedis();
    String result = jedis.get(key);
    close(jedis);
    return result;
}


// 存对象
public static String set(String key, Object value) {
    Jedis jedis = getJedis();


    // 对象转 string
    String s = JSON.toJSONString(value);
    String result = jedis.set(key, s);
    close(jedis);
    return result;
}


// 取对象值并转为对象
public static <T> T get(String key, Class<T> tClass) {
    Jedis jedis = getJedis();
    String result = jedis.get(key);
    close(jedis);
    T t = JSON.parseObject(result, tClass);
    return t;
}

}

公共类的使用

@Test

public void t4() {
    String res1 = RedisUtil.set("width", "100");
    System.out.println(res1);


    User user = new User("zs", "123");
    String res2 = RedisUtil.set("user", user);
    System.out.println(res2);
}


@Test
public void t5() {
    String result = RedisUtil.get("width");
    System.out.println(result);


    User user = RedisUtil.get("user",User.class);
    System.out.println(user);
}

以 byte[] 形式获取对象

@Test

public void t6() {
    Jedis jedis = RedisUtil.getJedis();
    jedis.auth("123");


    User user = new User("ls", "234");
    // 序列化
    byte[] serialize = SerializationUtils.serialize(user);
    String res = jedis.set("user2".getBytes(), serialize);
    System.out.println(res);


    jedis.close();
}


@Test
public void t7() {
    Jedis jedis = RedisUtil.getJedis();
    jedis.auth("123");


    byte[] bytes = jedis.get("user2".getBytes());


    // 反序列化
    User user = (User) SerializationUtils.deserialize(bytes);
    System.out.println(user);


    jedis.close();
}

Redis 的管道操作

主要解决频繁请求服务器造成的延迟问题。通过Redis的管道,先将命令放到客户端的一个 Pipeline 中,之后一次性将全部命令都发送到 Redis 服务,Redis 服务一次性的将全部的返回结果响应给客户端。

@Test

public void t8() {
    Jedis jedis = RedisUtil.getJedis();

// long start = System.currentTimeMillis();
//
// for (int i = 0; i < 10000; i ++) {
// jedis.incr("zan");
// }
//
// long end = System.currentTimeMillis();
//
// // 12865
// System.out.println(end - start);

    Pipeline pipelined = jedis.pipelined();
    long start = System.currentTimeMillis();


    for (int i = 0; i < 10000; i ++) {
        pipelined.incr("zan");
    }
    pipelined.syncAndReturnAll();


    long end = System.currentTimeMillis();


    // 324
    System.out.println(end - start);


}

Redis 应用

模拟 nginx 连接多台 tomcat 服务器,当一台服务器上登录时,其他服务器通过 cookie 识别其是否已登陆。

// Const.java

public interface Const {

//30分钟
int LIVETIME = 60*30;
//登陆状态标识
String ISLOGIN="islogin";

}

// RedisUtil.java

// 用于保存用户的登陆状态==>有时间限制
public static String setex(String key,int time,Object value){

    Jedis jedis = getResoucres();
    //把对象序列化为JSON字符串
    String string = JSON.toJSONString(value);
    //操作
    String result = jedis.setex(key, time,string );
    close(jedis);
    return result;
}


// 重新设置值生存时间
public static Long expire(String key ,int time){
    Jedis jedis = getResoucres();
    //操作 重新设置值生存时间
    Long result = jedis.expire(key, time);
    close(jedis);
    return result;
}



// UserController.java

@RestController
@RequestMapping("/user")
public class UserController {

@RequestMapping("/login")
public String login(String username, String password, HttpServletResponse response){
    if (username.equals("admin")&&password.equals("admin")) {
        User u = new User("admin", "admin");


        String uuid = UUID.randomUUID().toString();
        //保存数据到redis 作为登陆的状态
        //使用uuid作为redis保存的key值,为了防止key重复导致覆盖
        RedisUtil.setex(uuid, Const.LIVETIME,u);
        //把uuid的值保存到cookie当中,让其他服务器可以获取uuid来验证登陆状态
        //创建cookie对象
        Cookie cookie=new Cookie(Const.ISLOGIN, uuid);
        //设置cookie的存活时间
        cookie.setMaxAge(Const.LIVETIME);
        //设置作用范围
        cookie.setPath("/");
        //使用response写出cookie给客户端
        response.addCookie(cookie);
        return "ok";
    }
    return "no";
}
@RequestMapping("/check")
public String checkLogin(@CookieValue(Const.ISLOGIN) String uuid){
    /*Cookie[] cookies = request.getCookies();
    String uuid= null;
    for (Cookie cookie : cookies) {
        if (cookie.getName().equals(Const.ISLOGIN)) {
            uuid= cookie.getValue();
        }
    }*/
    //cookie有没有uuid存在
    if (uuid!=null){
        User user = RedisUtil.get(uuid, User.class);
        if (user != null) {
            System.out.println(user);
            return "is login";
        }
    }
    return "is not login";
}

}

Redis 其他配置

docker-compose.yml 映射 Redis 配置文件。

version: '3.1'
services:
nginx:

restart: always
image: daocloud.io/library/nginx:latest
container_name: nginx
ports:
  - 80:80

redis:

image: daocloud.io/library/redis:5.0.7
restart: always
container_name: redis
environment:
  - TZ=Asia/Shanghai
ports:
  - 6379:6379
volumes:
  - /opt/docker_nginx/conf.d/:/etc/nginx/conf.d
  - /opt/docker_nginx/img/:/data/img
  - /opt/docker_nginx/html/:/data/html
  - /opt/docker_nginx/conf/redis.conf:/usr/local/redis/redis.conf
command: ["redis-server","/usr/local/redis/redis.conf"]

// 关闭 docker
docker-compose down
// 创建文件夹
mkdir conf
// 要自己建立 redis.conf 文件,否则开启 docker 自动创建成文件夹
vi conf/redis.conf
// 开启 docker
docker-compose up -d

认证

requirepass admin

rdb

dbfilename redis.rdb
save 900 1
sava 300 10
save 60 10000

aof

appendonly yes
appendfilename "redis.aof"
appendfsync everysec

认证连接

redis-cli,命令 auth admin。

图形化界面,连接时添加上密码。

java,代码 jedis.auth(admin);

Redis 数据持久化机制。

RDB 是 Redis 默认的持久化机制。java培训RDB无法保证数据的绝对安全。

save 900 1,在900秒内,有1个key改变了,就执行RDB持久化。

save 300 10,在300秒内,有10个key改变了,就执行RDB持久化。

save 60 10000,在60秒内,有10000个key改变了,就执行RDB持久化。

AOF 持久化机制默认是关闭的,Redis 官方推荐同时开启 RDB 和 AOF 持久化,更安全,避免数据丢失。

AOF 持久化的速度,相对 RDB 较慢的,存储的是一个文本文件,并且会记录每次数据库的操作命令,到了后期文件会比较大,传输困难。

appendfsync always,每执行一个写操作,立即持久化到AOF文件中,性能比较低。

appendfsync everysec,每秒执行一次持久化。

appendfsync no,会根据操作系统不同,环境的不同,在一定时间内执行一次持久化。

原创作者:黎昏 


IT小尚
24 声望8 粉丝

尚硅谷IT培训学习爱好分享者