工程目录

sTunnel4连接redis_java

 

// 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 默认的持久化机制。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,会根据操作系统不同,环境的不同,在一定时间内执行一次持久化。

原创作者:黎昏