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中的数据即可。