Java操作Redis

创立我的项目

创立我的项目

增加依赖

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.2.4.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.xxxx</groupId>    <artifactId>redisdemo</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>redisdemo</name>    <description>Demo project for Spring Boot</description>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <!-- spring data redis 组件 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-redis</artifactId>            <!--                1.x 的版本默认采纳的连接池技术是 Jedis,                2.0 以上版本默认连接池是 Lettuce,                如果采纳 Jedis,须要排除 Lettuce 的依赖。             -->            <exclusions>                <exclusion>                    <groupId>io.lettuce</groupId>                    <artifactId>lettuce-core</artifactId>                </exclusion>            </exclusions>        </dependency>        <!-- jedis 依赖 -->        <dependency>            <groupId>redis.clients</groupId>            <artifactId>jedis</artifactId>        </dependency>        <!-- web 组件 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <!-- test 组件 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies></project>

配置文件

spring:  redis:    # Redis服务器地址    host: 192.168.10.100    # Redis服务器端口    port: 6379    # Redis服务器明码    password: root    # 抉择哪个库,默认0库    database: 0    # 连贯超时工夫    timeout: 10000ms    jedis:      pool:        # 最大连接数,默认8        max-active: 1024        # 最大连贯阻塞等待时间,单位毫秒,默认-1ms        max-wait: 10000ms        # 最大闲暇连贯,默认8        max-idle: 200        # 最小闲暇连贯,默认0        min-idle: 5

Java怎么连贯Redis?

/** * 连贯Redis */@Testpublic void initConn01() {    // 创立jedis对象,连贯redis服务    Jedis jedis = new Jedis("192.168.10.100", 6379);    // 设置认证明码    jedis.auth("root");    // 指定数据库 默认是0    jedis.select(1);    // 应用ping命令,测试连贯是否胜利    String result = jedis.ping();    System.out.println(result);// 返回PONG    // 增加一条数据    jedis.set("username", "zhangsan");    // 获取一条数据    String username = jedis.get("username");    System.out.println(username);    // 开释资源    if (jedis != null)        jedis.close();}

通过Redis连接池获取连贯对象并操作服务器

/** * 通过Redis连接池获取连贯对象 */@Testpublic void initConn02() {    // 初始化redis客户端连接池    JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "192.168.10.100", 6379, 10000, "root");    // 从连接池获取连贯    Jedis jedis = jedisPool.getResource();    // 指定数据库 默认是0    jedis.select(2);    // 应用ping命令,测试连贯是否胜利    String result = jedis.ping();    System.out.println(result);// 返回PONG    // 增加一条数据    jedis.set("username", "zhangsan");    // 获取一条数据    String username = jedis.get("username");    System.out.println(username);    // 开释资源    if (jedis != null)        jedis.close();}

封装JedisUtil对外提供连贯对象获取办法

@Configurationpublic class RedisConfig {    //服务器地址    @Value("${spring.redis.host}")    private String host;    //端口    @Value("${spring.redis.port}")    private int port;    //明码    @Value("${spring.redis.password}")    private String password;    //超时工夫    @Value("${spring.redis.timeout}")    private String timeout;    //最大连接数    @Value("${spring.redis.jedis.pool.max-active}")    private int maxTotal;    //最大连贯阻塞等待时间    @Value("${spring.redis.jedis.pool.max-wait}")    private String maxWaitMillis;    //最大闲暇连贯    @Value("${spring.redis.jedis.pool.max-idle}")    private int maxIdle;    //最小闲暇连贯    @Value("${spring.redis.jedis.pool.min-idle}")    private int minIdle;    @Bean    public JedisPool redisPoolFactory(){        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();        //留神值的转变  jedisPoolConfig.setMaxWaitMillis(Long.parseLong(maxWaitMillis.substring(0,maxWaitMillis.length()-2)));        //留神属性名        jedisPoolConfig.setMaxTotal(maxTotal);        jedisPoolConfig.setMaxIdle(maxIdle);        jedisPoolConfig.setMinIdle(minIdle);        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, Integer.parseInt(timeout.substring(0,                timeout.length() - 2)), password);        return jedisPool;    }}

Java操作Redis五种数据类型

连贯与开释

@Autowiredprivate JedisPool jedisPool;private Jedis jedis = null;//初始化jedis对象实例@Beforepublic void initConn(){    jedis = jedisPool.getResource();}//开释资源@Afterpublic void closeConn(){    if (jedis!=null){        jedis.close();    }}

操作String

// 1.操作String@Testpublic void testString() {   // 增加一条数据   jedis.set("username", "zhangsan");   jedis.set("age", "18");      // 增加多条数据 参数奇数为key 参数偶数为value   jedis.mset("address", "bj", "sex", "1");      // 获取一条数据   String username = jedis.get("username");   System.out.println(username);      // 获取多条数据   List<String> list = jedis.mget("username", "age", "address", "sex");   for (String str : list) {      System.out.println(str);   }      // 删除   //jedis.del("username");}

操作hash

// 2.操作Hash@Testpublic void testHash() {   /*    * 增加一条数据    *     参数一:redis的key    *     参数二:hash的key    *     参数三:hash的value    */   jedis.hset("userInfo", "name", "lisi");      // 增加多条数据   Map<String, String> map = new HashMap<>();   map.put("age", "20");   map.put("sex", "1");   jedis.hmset("userInfo", map);      // 获取一条数据   String name = jedis.hget("userInfo", "name");   System.out.println(name);      // 获取多条数据   List<String> list = jedis.hmget("userInfo", "age", "sex");   for (String str : list) {      System.out.println(str);   }      // 获取Hash类型所有的数据   Map<String, String> userMap = jedis.hgetAll("userInfo");   for (Entry<String, String> userInfo : userMap.entrySet()) {      System.out.println(userInfo.getKey() + "--" + userInfo.getValue());   }      // 删除 用于删除hash类型数据   //jedis.hdel("userInfo", "name");}

操作list

    // 3.操作list   @Test   public void testList() {      // 左增加(上)//    jedis.lpush("students", "Wang Wu", "Li Si");            // 右增加(下)//    jedis.rpush("students", "Zhao Liu");            // 获取 start起始下标 end完结下标 蕴含关系      List<String> students = jedis.lrange("students", 0, 2);      for (String stu : students) {         System.out.println(stu);      }            // 获取总条数      Long total = jedis.llen("students");      System.out.println("总条数:" + total);            // 删除单条 删除列表中第一次呈现的Li Si//    jedis.lrem("students", 1, "Li Si");            // 删除多条//    jedis.del("students");   }

操作set

// 4.操作set-无序@Testpublic void testSet() {   // 增加数据   jedis.sadd("letters", "aaa", "bbb", "ccc", "ddd", "eee");      // 获取数据   Set<String> letters = jedis.smembers("letters");   for (String letter: letters) {      System.out.println(letter);   }        //获取总条数    Long total = jedis.scard("letters");    System.out.println(total);      // 删除   //jedis.srem("letters", "aaa", "bbb");}

操作sorted set

// 5.操作sorted set-有序@Testpublic void testSortedSet() {   Map<String, Double> scoreMembers = new HashMap<>();   scoreMembers.put("zhangsan", 7D);   scoreMembers.put("lisi", 3D);   scoreMembers.put("wangwu", 5D);   scoreMembers.put("zhaoliu", 6D);   scoreMembers.put("tianqi", 2D);      // 增加数据   jedis.zadd("score", scoreMembers);      // 获取数据   Set<String> scores = jedis.zrange("score", 0, 4);   for (String score: scores) {      System.out.println(score);   }      // 获取总条数   Long total = jedis.zcard("score");   System.out.println("总条数:" + total);      // 删除   //jedis.zrem("score", "zhangsan", "lisi");}

Redis中以层级关系、目录模式存储数据

// Redis中以层级关系、目录模式存储数据@Testpublic void testdir(){    jedis.set("user:01", "user_zhangsan");    System.out.println(jedis.get("user:01"));}

设置key的生效工夫

Redis 有四个不同的命令能够用于设置键的生存工夫(键能够存在多久)或过期工夫(键什么时候会被删除) :

EXPlRE <key> <ttl> :用于将键key 的生存工夫设置为ttl 秒。

PEXPIRE <key> <ttl>:用于将键key 的生存工夫设置为ttl 毫秒。

EXPIREAT <key> < timestamp>:用于将键key 的过期工夫设置为timestamp所指定的秒数工夫戳。

PEXPIREAT <key> < timestamp > :用于将键key 的过期工夫设置为timestamp所指定的毫秒数工夫戳。

TTL:获取的值为-1阐明此key没有设置有效期,当值为-2时证实过了有效期。

@Testpublic void testExpire() {    // 办法一:    jedis.set("code", "test");    jedis.expire("code", 180);// 180秒    jedis.pexpire("code", 180000L);// 180000毫秒    jedis.ttl("code");// 获取秒    // 办法二:    jedis.setex("code", 180, "test");// 180秒    jedis.psetex("code", 180000L, "test");// 180000毫秒    jedis.pttl("code");// 获取毫秒    // 办法三:    SetParams setParams = new SetParams();    //不存在的时候能力设置胜利    // setParams.nx();    // 存在的时候能力设置胜利    setParams.xx();    //设置生效工夫,单位秒    // setParams.ex(30);    //查看生效工夫,单位毫秒    setParams.px(30000);    jedis.set("code","test",setParams);}

获取所有key&事务&删除

   // 获取所有key   @Test   public void testAllKeys() {      // 以后库key的数量      System.out.println(jedis.dbSize());      // 以后库key的名称      Set<String> keys = jedis.keys("*");      for (String key: keys) {         System.out.println(key);      }   }    // 操作事务   @Test   public void testMulti() {      Transaction tx = jedis.multi();      // 开启事务      tx.set("tel", "10010");            // 提交事务//    tx.exec();            // 回滚事务      tx.discard();   }      // 删除   @Test   public void testDelete() {      // 删除 通用 实用于所有数据类型      jedis.del("score");   }

操作byte

SerializeUtil.java

package com.xxxx.util;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;/** * 序列化工具类 */public class SerializeUtil {      /**    * 将java对象转换为byte数组 序列化过程    */   public static byte[] serialize(Object object) {      ObjectOutputStream oos = null;      ByteArrayOutputStream baos = null;      try {         // 序列化         baos = new ByteArrayOutputStream();         oos = new ObjectOutputStream(baos);         oos.writeObject(object);         byte[] bytes = baos.toByteArray();         return bytes;      } catch (Exception e) {         e.printStackTrace();      }      return null;   }   /**    * 将byte数组转换为java对象  反序列化    */   public static Object unserialize(byte[] bytes) {      if(bytes == null)return null;      ByteArrayInputStream bais = null;      try {         // 反序列化         bais = new ByteArrayInputStream(bytes);         ObjectInputStream ois = new ObjectInputStream(bais);         return ois.readObject();      } catch (Exception e) {         e.printStackTrace();      }      return null;   }}

User.java

package com.xxxx.entity;import java.io.Serializable;public class User implements Serializable {    private static final long serialVersionUID = 9148937431079191022L;    private Integer id;    private String username;    private String password;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    @Override    public String toString() {        return "User{" +                "id=" + id +                ", username='" + username + '\'' +                ", password='" + password + '\'' +                '}';    }}

JedisTest.java

// 操作byte@Testpublic void testByte() {    User user = new User();    user.setId(2);    user.setUsername("zhangsan");    user.setPassword("123");    // 序列化    byte[] userKey = SerializeUtil.serialize("user:" + user.getId());    byte[] userValue = SerializeUtil.serialize(user);    jedis.set(userKey, userValue);    // 获取数据    byte[] userResult = jedis.get(userKey);    // 反序列化    User u = (User) SerializeUtil.unserialize(userResult);    System.out.println(u);}

Redis搭建主从复用

 Redis反对主从复用。数据能够从主服务器向任意数量的从服务器上同步,同步应用的是公布/订阅机制。Mater Slave的模式,从Slave向Master发动SYNC命令。

 能够是1 Master 多Slave,能够分层,Slave下能够再接Slave,可扩大成树状构造。

 因为没有两台电脑,所以只能在一台机器上搭建两个Redis服务端。

 这里应用单机来模仿redis 主从服务器 ,实现读写拆散配置。

读写拆散

创立三个目录(数据文件、日志文件、配置文件)

复制redis.conf至/opt/redis/conf目录下

批改redis-common.conf公共配置文件

正文掉bind 127.0.0.1

敞开保护模式,批改为no

正文公共配置端口

批改为后盾启动

正文过程编号记录文件

正文公共配置日志文件

正文公共配置数据文件、批改数据文件门路

 在默认状况下,Redis 将数据库快照保留在名字为 dump.rdb 的二进制文件中。当然,这里能够通过批改redis.conf 配置文件来对数据存储条件进行定义,规定在“ N 秒内数据集至多有 M 个改变”这一条件被满足时,主动保留一次数据集。也能够通过调用save 或bgsave ,手动让Redis进行数据集保留操作

dbfilename和dir组合应用,dbfilename找dir门路生成数据文件

增加从服务器拜访主服务器认证

增加拜访认证

正文公共配置追加文件

 依据需要配置是否关上追加文件选项

 appendonly yes -> 每当Redis执行一个扭转数据集的命令时(比方 SET),这个命令就会被追加到 AOF 文件的开端。这样的话,当Redis从新启时,程序就能够通过从新执行 AOF文件中的命令来达到重建数据集的目标

 

 appendfilename和dir组合应用,找dir(/opt/redis/data)门路生成数据文件

从服务器默认是只读不容许写操作(不必批改)

增加3个服务的公有配置文件

 touch或者vi都能够创立空白文件

 touch间接创立空白文件,vi创立并且进入编辑模式,:wq创立胜利,否则不创立

redis-6379.conf

#援用公共配置include /opt/redis/conf/redis-common.conf#过程编号记录文件pidfile /var/run/redis-6379.pid#过程端口号port 6379#日志记录文件logfile "/opt/redis/log/redis-6379.log"#数据记录文件dbfilename dump-6379.rdb#追加文件名称appendfilename "appendonly-6379.aof"#上面的配置无需在6379里配置#备份服务器从属于6379举荐配置配局域网IPslaveof 192.168.10.100 6379

 复制redis-6379.conf的内容至redis-6380.conf,redis-6381.conf并且批改其内容,将6379替换即可。

运行3个redis过程

查看redis服务器主从状态

redis-6379

redis-6380

redis-6381

在主服务器下增加数据 并测试从服务器数据是否失常显示

从服务器只读,不容许写操作

主备切换

主从节点redis.conf配置

参照读写拆散的相应配置

批改sentinel-common.conf 哨兵公共配置文件

从redis解压目录下复制sentinel.conf至/opt/redis/conf/

cp sentinel.conf /opt/redis/conf/sentinel-common.conf

正文哨兵监听过程端口号

 批示Sentinel去监督一个名为master的主服务器,这个主服务器的IP地址为 127.0.0.1,端口号为6379,而将这个主服务器判断为生效至多须要1个(个别设置为2个)。Sentinel批准 (只有批准Sentinel的数量不达标,主动故障迁徙就不会执行)。

 这个要配局域网IP,否则近程连不上。

设置master和slaves的明码

Sentinel认为服务器曾经断线所需的毫秒数

 若sentinel在该配置值内未能实现failover操作(即故障时master/slave主动切换),则认为本次failover失败。

敞开保护模式,批改为no

批改为后盾启动

增加3个哨兵的公有配置文件

touch或者vi都能够创立空白文件

touch间接创立空白文件,vi创立并且进入编辑模式,:wq创立胜利,否则不创立

sentinel-26379.conf

#援用公共配置include /opt/redis/conf/sentinel-common.conf#过程端口号port 26379#过程编号记录文件pidfile /var/run/sentinel-26379.pid#日志记录文件(为了不便查看日志,先正文掉,搭好环境后再关上)logfile "/opt/redis/log/sentinel-26379.log"

 复制sentinel-26379.conf的内容至sentinel-26380.conf ,sentinel-26381.conf并且批改其内容,将26379替换即可。

启动测试

启动3个redis服务

/usr/local/redis/bin/redis-server /opt/redis/conf/redis-6379.conf/usr/local/redis/bin/redis-server /opt/redis/conf/redis-6380.conf/usr/local/redis/bin/redis-server /opt/redis/conf/redis-6381.conf

启动3个哨兵服务

/usr/local/redis/bin/redis-sentinel /opt/redis/conf/sentinel-26379.conf/usr/local/redis/bin/redis-sentinel /opt/redis/conf/sentinel-26380.conf/usr/local/redis/bin/redis-sentinel /opt/redis/conf/sentinel-26381.conf

查看主从状态

redis-6379

redis-6380

redis-6381

检测哨兵性能是否配置胜利

kill -9 终止redis-6379,查看哨兵是否选举了新的主节点

已选举6380为主节点,从节点目前只有6381

重新启动6379节点,再次查看主从状态

发现6379已被发现且成为从节点

6380之前不能够写操作,当初能够写操作,因为已成为主节点。

最初,公共配置文件批改为后盾启动,公有配置文件关上日志记录文件,环境搭建胜利。## Java操作Redis

jedis.set("code","test",setParams);

}

#### 获取所有key&事务&删除

// 获取所有key
@Test
public void testAllKeys() {

  // 以后库key的数量  System.out.println(jedis.dbSize());  // 以后库key的名称  Set<String> keys = jedis.keys("*");  for (String key: keys) {     System.out.println(key);  }

}

// 操作事务

@Test
public void testMulti() {

  Transaction tx = jedis.multi();  // 开启事务  tx.set("tel", "10010");    // 提交事务

// tx.exec();

    // 回滚事务  tx.discard();

}

// 删除
@Test
public void testDelete() {

  // 删除 通用 实用于所有数据类型  jedis.del("score");

}

**增加拜访认证**![](https://img-blog.csdnimg.cn/20201224111709664.png#pic_center)**正文公共配置追加文件** 依据需要配置是否关上追加文件选项 `appendonly yes` -> 每当Redis执行一个扭转数据集的命令时(比方 SET),这个命令就会被追加到 AOF 文件的开端。这样的话,当Redis从新启时,程序就能够通过从新执行 AOF文件中的命令来达到重建数据集的目标![](https://img-blog.csdnimg.cn/20201224111721525.png#pic_center)  appendfilename和dir组合应用,找dir(/opt/redis/data)门路生成数据文件![](https://img-blog.csdnimg.cn/202012241117342.png#pic_center)**从服务器默认是只读不容许写操作(不必批改)**![](https://img-blog.csdnimg.cn/20201224111746884.png#pic_center)