Redis - Jedis简介及SpringDataRedis的使用

Jedis

Jedis是Redis官方推荐的Java连接开发工具,使用Jedis操作Redis需要导入commons-pool2和jedis的jar包。

 

常用API

基本与操作命令一致,下面所示只是常用API,如果想了解更多API可以百度搜索,这里不详细列出。

/**
 * 创建Jedis对象
 * host:Redis服务器地址
 * port:Redis服务端口
 */
Jedis jedis = new Jedis(String host, String port);

jedis.set(String key,String value);   // 设置字符串类型的数据

jedis.get(String key);    // 获取字符串类型的数据

jedis.hset(String key , String field, String value);     // 设置哈希类型的数据

jedis.hget(String key,String field);       // 获得哈希类型的数据

jedis.lpush(String key,String value1,String value2...);     // 设置列表类型的数据

jedis.lpop(String key);        // 列表左面弹栈

jedis.rpop(String key);        // 列表右面弹栈

jedis.del(String key);         // 删除指定的key

 

Jedis基本操作

/**
 * 这里以String类型举例,其他类似
 */
public void testJedis(){
    // 设置IP地址和端口
    Jedis jedis = new Jedis("localhost",6379);
    // 设置数据
    jedis.set("name","lcy");
    // 获取数据
    String name = jedis.get("name");
    // 打印数据
    System.out.println(name);
    // 释放资源
    jedis.close();
}

 

Jedis连接池

Jedis连接资源的创建与销毁是很消耗程序性能,所以Jedis为我们提供了Jedis的池化技术

public void testJedisPool(){
    // 获取连接池配置对象,设置配置项
    JedisPoolConfig config = new JedisPoolConfig();
    // 设置最大连接数
    config.setMaxTotal(30);
    // 设置最大空闲连接数
    config.setMaxIdle(10);

    // 获取连接池
    JedisPool jedisPool = new JedisPool(config,"localhost",6379);
    // 获取Jedis核心对象
    Jedis jedis = null;
    try{
        jedis = jedisPool.getResource();
        // 设置数据
        jedis.set("name","lcy");
        // 获取数据
        String name = jedis.get("name");        
        // 打印数据
        System.out.println(name);
    }catch(Exception e){
        e.printStackTrace();
    }finally{
		if(jedis != null){
			jedis.close();
		}
		// 服务器关闭时,释放pool资源
		if(jedisPool != null){
			jedisPool.close();
		}
	}
}

SpringDataRedis

SpringDataRedis是Spring大家族的一部分,提供了在Spring应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装。

RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。

 

SpringDataRedis功能

1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类

2.针对Jedis客户端中大量api进行了归类封装

①SetOperations:针对set类型数据操作

②ZSetOperations:针对zset类型数据操作

③HashOperations:针对map类型的数据操作

④ListOperations:针对list类型的数据操作

⑤ValueOperations:简单K-V操作

程序工程搭建 - SpringDataRedis简单使用

一、创建Maven工程(Jar工程),命名为SpringDataRedisDemo

二、引入Spring、Jedis、SpringDataRedis的依赖

<!-- Junit单元测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>
<!-- spring - test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>

<!-- 缓存 -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.8.1</version>
</dependency>
<!-- spring-data-Redis -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.7.2.RELEASE</version>
</dependency>

三、在src/main/resources下创建redis-config.properties

# Redis服务器地址
redis.host=10.35.33.33
# Redis服务端口
redis.port=6379
# Redis密码 - 安装Redis时最好设置。我曾因没设置密码,导致服务器感染挖矿病毒
redis.pass=123456
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true

四、 在src/main/resources下创建applicationContext-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 引入properties配置文件 -->
    <context:property-placeholder location="classpath*:*.properties" />

    <!-- redis 相关配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
    <bean id="JedisConnectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
          p:host-name="${redis.host}"
          p:port="${redis.port}"
          p:password="${redis.pass}"
          p:pool-config-ref="poolConfig"/>
    
    <!-- RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="JedisConnectionFactory" />
    </bean>
</beans>

五、建立测试Java文件【每一种测试的方法代码在后面贴出】

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestString {
    @Autowired
    private RedisTemplate redisTemplate;

    
}

String操作测试

// 字符串存取操作
@Test
public void testStringSet(){
    // String类型 - 存储
    redisTemplate.boundValueOps("name").set("lcy");
}

@Test
public void testStringGet(){
    // 取值
    String name = (String) redisTemplate.boundValueOps("name").get();
    System.out.println(name);
}

@Test
public void testStringDel(){
    // 删除
    redisTemplate.delete("name");
}

List操作测试

// List存取操作
@Test
public void testListLeftPush(){
    // 左存值
    redisTemplate.boundListOps("myListKey").leftPush("001");
    redisTemplate.boundListOps("myListKey").leftPush("002");
    redisTemplate.boundListOps("myListKey").leftPush("003");
    redisTemplate.boundListOps("myListKey").leftPush("004");
}

@Test
public void testListRightPush(){
    // 右存值
    redisTemplate.boundListOps("myListKey").rightPush("005");
    redisTemplate.boundListOps("myListKey").rightPush("006");
    redisTemplate.boundListOps("myListKey").rightPush("007");
    redisTemplate.boundListOps("myListKey").rightPush("008");
}

@Test
public void testListRange(){
    // 取值
    List<String> myListKey = redisTemplate.boundListOps("myListKey").range(0, -1);
    for (String s : myListKey) {
        System.out.println(s);
    }
}

@Test
public void testListDel(){
    // 删除List
    redisTemplate.delete("myListKey");
}

Hash操作测试

// Hash
@Test
public void testHashPut(){
    // 存值
    redisTemplate.boundHashOps("keyname1").put("name","zs");
    redisTemplate.boundHashOps("keyname1").put("age","20");
    redisTemplate.boundHashOps("keyname1").put("phone","12345678910");
    redisTemplate.boundHashOps("keyname1").put("email","[email protected]");
}

@Test
public void testHashGetOne(){
    // 取一个值
    String name = (String) redisTemplate.boundHashOps("keyname1").get("name");
    String age = (String) redisTemplate.boundHashOps("keyname1").get("age");
    System.out.println("姓名:" + name + "\t年龄:" + age);
}

@Test
public void testHashGetAll(){
    // 获取所有的值
    Map<String, String> user = redisTemplate.boundHashOps("keyname1").entries();
    Set<Map.Entry<String, String>> entries = user.entrySet();
    for (Map.Entry<String, String> entry : entries) {
        System.out.println("key = " + entry.getKey());
        System.out.println("value = " + entry.getValue());
    }
}

@Test
public void testHashDelOne(){
    // 删除一个值
    redisTemplate.boundHashOps("keyname1").delete("name");
}

@Test
public void testHashDelAll(){
    // 删除所有
    redisTemplate.delete("keyname1");
}

对象操作测试

一、创建People对象类

// 须实现序列化接口
public class Person implements Serializable {
    private String name;
    private String phone;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

二、创建存储Key值的常量类Constants

在真实开发中,Key是非常珍贵的,一般都是根据业务来存,通过hash的方式。比如这里是一个用户相关的业务(userServiced),则就可以用userService作为主Key。

public class Constants {
    public final static String CONTENT_LIST_REDIS = "userService";
}

三、测试代码

// 对象
@Test
public void testObjSet(){
    Person person = new Person();
    person.setAge(20);
    person.setName("lcy");
    person.setPhone("123456789");
    Person person1 = new Person();
    person1.setAge(22);
    person1.setName("jyqc");
    person1.setPhone("987654321");
    List<Person> personList = new ArrayList();
    personList.add(person);
    personList.add(person1);
    // key是很珍贵的,真正开发中,根据业务来存,即通过hash
    redisTemplate.boundHashOps("userService").put("person",personList);
}

@Test
public void testObjGet(){
    List<Person> res = (List<Person>) redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).get("person");
    for (Person per : res) {
        System.out.println(per.getName());
    }
}

项目中运用举例 - 广告

获取广告数据的时候先从redis中获取, 如果获取到数据则直接返回, 就不用访问数据库了。如果获取不到数据, 可以从数据库中查询, 查询到后放入redis中一份, 下次就可以直接从redis中查询到,这样大大降低了数据库的高并发访问压力。

当新增广告的时候怎么办?

比如分类id为1的广告新增加1个,从Redis获取数据是不会获取到这个新增的广告的。那么我们可以在新增广告的方法里,在存入MySQL之后,我们根据分类ID来删除对应分类的广告集合(全部删除完),这样操作简单。下一次进入页面,获取广告时,Redis里为空,它就会先从MySQL数据库中获取一份,并存入Redis。也就是说第一次从MySQL获取的数据,下一次就是从Redis获取的数据了。

当删除广告的时候怎么办?

比如分类id为1的广告删除1个,这个操作方式与新增时相似。先根据广告id去从MySQL获取这个广告对应的分类id,然后根据分类id删除Redis中对应广告集合,然后再去删除MySQL中这条广告的数据。

当更新广告的时候怎么办?

比如更新分类id为1的广告,将其分类id改为2。我们来分析下过程,将这个广告从分类1变成分类2,是不是就相当于分类1的广告减少了1个,分类2的广告增加了一个。既然清楚了这个原理就好办了,将分类1和分类2的Redis数据都清理一下就行了。具体流程:根据更新广告的广告id去查询它原来的分类id,根据原来的分类id来清理原来分类在Redis中的数据。然后根据更新之后的广告对象的分类id去清理这个分类在Redis中的数据即可。

发布了59 篇原创文章 · 获赞 13 · 访问量 2505

猜你喜欢

转载自blog.csdn.net/qq_40885085/article/details/104096560