redis的安裝並在java中初步使用(spring配置redis)

lkj41110發表於2017-01-05

redis介紹

官方介紹:
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

redis作為nosql(非關係型資料庫)其中一種,是一個高效能的key-value資料庫,相比於支援string(字串)、list(連結串列)、set(集合)、zset(sorted set –有序集合)和hash(雜湊型別),可以將儲存在記憶體的鍵值對資料持久化到硬碟,可以使用複製特性來擴充套件讀效能,還可以使用客戶端分片來擴充套件寫效能。

更多redis介紹:

redis在windows下載和使用

要下載windows版本的redis,必須要有redis-server.exe:服務程式(之前在官網下沒有這個檔案,不知道是因為版本問題還是不是windows版本的問題)
windows的下載版本:http://download.csdn.net/download/jimlung/9609681
Linux版教程本:http://blog.csdn.net/chenggong2dm/article/details/6100001

遇到的問問題:
[3416] 05 Jan 11:38:39.089 # Warning: no config file specified, using the defaul
t config. In order to specify a config file use redis-server /path/to/redis.conf

[3416] 05 Jan 11:38:39.109 # Creating Server TCP listening socket *:6379: bind:
No such file or directory
或者遇到
Creating Server TCP listening socket 127.0.0.1:6379: bind: No error

解決方法遇到上面的錯誤

  • 一種情況是你沒有指定redis的配置檔案,他會使用預設的redis.conf檔案,而windows裡的是redis.windows.conf。你可以啟動命令臺輸入:redis-server redis.windows.conf
  • 還有一種是已經啟用的redis,導致6379埠被佔用,把原來的關閉即可。
  • 依次使用下列命令
  • redis-cli.exe
  • shutdown
  • exit
  • redis-server.exe
    成功開啟後即可看見成功介面:
    這裡寫圖片描述
    這樣我們相當於啟動了redis的伺服器,當我們使用redis時,必須開著這個視窗。

使用redis

完成上面的步驟後,另開一個cmd視窗,執行redis-cli.exe程式,即可執行redis。

127.0.0.1:6379> set a aa
OK
127.0.0.1:6379> get a
"aa"

我們儲存了key為a的字串aa,在獲取了名字為a的字串,redis的使用是不是很簡單呢。當然我們還可以儲存列表,集合等5種不同的資料型別。
redis的全面的使用手冊:http://www.yiibai.com/redis/redis_quick_guide.html

在java使用redis

maven的包:

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.8.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.3.2</version>
    </dependency>
@Test
    public void testRedis() {
        Jedis jj = new  Jedis("localhost");  
        jj.set("key1", "I am value 1");  
        String ss = jj.get("key1");  
        System.out.println(ss);
    }

通過測試可以獲取正確的字串,並且從redis-cli.exe也可以獲取到在java中儲存的字串。

redis整合於spring框架並使用

一樣需要匯入maven包。

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.8.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.3.2</version>
    </dependency>

建立redis的配置檔案 redis.properties

#redis config
redis.pass=
redis.pool.maxTotal=105
redis.pool.maxIdle=10
redis.pool.maxWaitMillis=5000
redis.pool.testOnBorrow=true

#redis \u5355\u8282\u70B9\u914D\u7F6E
redis.ip=127.0.0.1
redis.port=6379

spring的配置檔案:

<?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: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">

    <!-- 快取的層級 -->
    <context:component-scan base-package="com.yingjun.ssm.cache" />
    <!-- 引入redis配置 -->
    <context:property-placeholder location="classpath:redis.properties"
        ignore-unresolvable="true" />


    <!-- redis單節點資料庫連線配置 -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.ip}" />
        <property name="port" value="${redis.port}" />
        <property name="password" value="${redis.pass}" />
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean>

    <!-- redisTemplate配置,redisTemplate是對Jedis的對redis操作的擴充套件,有更多的操作,封裝使操作更便捷 -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
    </bean>
</beans>

redis的工具類

package com.yingjun.ssm.cache;

import com.yingjun.ssm.util.ProtoStuffSerializerUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;

/**
 * redis快取
 * 
 * @author yingjun
 *
 */
@Component
public class RedisCache {


    public final static String CAHCENAME="cache";//快取名
    public final static int CAHCETIME=60;//預設快取時間

    //主要通過注入的redisTemplate對redis進行操作
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public <T> boolean putCache(String key, T obj) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serialize(obj);
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.setNX(bkey, bvalue);
            }
        });
        return result;
    }

    public <T> void putCacheWithExpireTime(String key, T obj, final long expireTime) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serialize(obj);
        redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                connection.setEx(bkey, expireTime, bvalue);
                return true;
            }
        });
    }

    public <T> boolean putListCache(String key, List<T> objList) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.setNX(bkey, bvalue);
            }
        });
        return result;
    }

    public <T> boolean putListCacheWithExpireTime(String key, List<T> objList, final long expireTime) {
        final byte[] bkey = key.getBytes();
        final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                connection.setEx(bkey, expireTime, bvalue);
                return true;
            }
        });
        return result;
    }

    public <T> T getCache(final String key, Class<T> targetClass) {
        byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
            @Override
            public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.get(key.getBytes());
            }
        });
        if (result == null) {
            return null;
        }
        return ProtoStuffSerializerUtil.deserialize(result, targetClass);
    }

    public <T> List<T> getListCache(final String key, Class<T> targetClass) {
        byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
            @Override
            public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.get(key.getBytes());
            }
        });
        if (result == null) {
            return null;
        }
        return ProtoStuffSerializerUtil.deserializeList(result, targetClass);
    }

    /**
     * 精確刪除key
     * 
     * @param key
     */
    public void deleteCache(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 模糊刪除key
     * 
     * @param pattern
     */
    public void deleteCacheWithPattern(String pattern) {
        Set<String> keys = redisTemplate.keys(pattern);
        redisTemplate.delete(keys);
    }

    /**
     * 清空所有快取
     */
    public void clearCache() {
        deleteCacheWithPattern(RedisCache.CAHCENAME+"|*");
    }
}

這樣我們在我們的專案裡可以使用RedisCache這個類裡的方法來獲取我們的快取了。

@Autowired
private RedisCache cache;

public List<Goods> getGoodsList(int offset, int limit) {
        String cache_key = RedisCache.CAHCENAME + "|getGoodsList|" + offset + "|" + limit;
        List<Goods> result_cache = cache.getListCache(cache_key, Goods.class);
        if (result_cache != null) {
            LOG.info("get cache with key:" + cache_key);
        } else {
            // 快取中沒有再去資料庫取,並插入快取(快取時間為60秒)
            result_cache = goodsDao.queryAll(offset, limit);
            cache.putListCacheWithExpireTime(cache_key, result_cache, RedisCache.CAHCETIME);
            LOG.info("put cache with key:" + cache_key);
            return result_cache;
        }
        return result_cache;
    }

上面的例子是先從redis記憶體中獲取,如果不為空,則不用從資料庫中獲取,如果為空從資料庫中獲取在把資料儲存到redis中,以便下次獲取。

完整的例子github:https://github.com/lkj41110/beauty_ssm/tree/master/src

當然redis還有很多用處,目前專案裡只是把它作為一個快取的機制來減少對資料庫的讀取加快資料的讀取速度

相關文章