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());
}
}
注意:通過SpringDataRedis來進行存儲數據,會對Key和Value進行一個二進制的處理。比如存的key是"name",實際存入到Redis的是類似於"\xac\xed\x00\x05t\x00\x04name",存入的value是"lcy",實際存入到Redis的是類似於"\xac\xed\x00\x05t\x00\x03lcy"這樣的。
項目中運用舉例 - 廣告
獲取廣告數據的時候先從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中的數據即可。