Redis

Redis介绍

redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写。企业开发通常采用Redis来实现缓存。同类的产品还有Memcache 、Memcached 、MongoDB等。

什么是Redis

Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。 Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用。 Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。

Redis出现的原因
  • 由于关系型数据库检索效率低(因为有大量的io操作),为了提高效率,使用redis 远程字典
  • 像淘宝京东这样的首页每天有大量的人访问,对数据库造成很大的访问压力,甚至是瘫痪。那如何解决呢?我们通常的做法有两种:一种是数据缓存、一种是网页静态化。我们今天讨论第一种解决方案。
Redis的作用:

把数据存放到内存中,作为数据库使用缓存技术

Spring Data Redis

Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
spring-data-redis针对jedis提供了如下功能:

  • 连接池自动管理,提供了一个高度封装的“RedisTemplate”类
  • 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
  • ValueOperations:简单K-V操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:针对map类型的数据操作
  • ListOperations:针对list类型的数据操作

小知识

3.x(支持集群) 2.x不支持集群 (3.0)
副版本号为偶数时,表示是稳定版本,建议在生产环境中使用
副版本号为奇数时,表示是测试版本,不建议在生产环境中是用

没有Windows版本哦
因为目前Linux版本已经相当稳定,而且用户量很大,无需开发windows版本,反而会带来兼容性等问题。

Linux版本Redis的安装

这里介绍的是单机版安装

第一步 安装gcc:

由于redis本身是采用c++ 编写的,所以解压完成后,需要编译和安装。
所以先要在系统中安装 c++的编译器 gcc-c++

切换管理员用户 su root

输入命令 yum install -y gcc-c++

Redis 是国产 redisem什么牌子_java

第二步 安装redis
  1. 使用 root 用户登录,把redis安装文件(xxx.gz结尾的是linux系统的压缩包) 拷贝到linux系统中
  2. 解压这个文件

解压命令 tar –zxvf redis-3.0.0.tar.gz

  1. 进入解压后的目录,对里面的文件进行编译和安装

cd redis-3.0.0

这里采用编译和安装同时进行的方式。

make install PREFIX=/usr/local/redis
/usr/local/redis是redis的安装路径,目录名不是一定要叫redis可以自己定义

  1. 进入redis的安装路径,查看里面的文件

cd usr/local/redis/bin
其中 redis-server文件就是redis的启动文件

  1. ./redis-server 运行这个文件,如果看到一个图形界面,界面中显示redis的版本、软件位数、监听的端口(6379)、PID等信息
    说明redis的安装和启动成功
注意: 前面的启动叫做前置启动。

前置启动的特点,当redis 启动后,linux操作界面将不能输入执行其他命令!!!

第三步 启动Redis

redis的启动,分为前置启动和后置启动两种:

  1. 前置启动

启动命令 ./redis-server

退出前置启动的方式 ctrl+c

  1. 后置启动
  • 到redis的解压目录中拷贝 redis.conf 到 redis的安装目录中(和redis-server在同一个目录)

cp opt/redis-3.0.0/redis.conf usr/local/redis/bin

  • 打开这个文件(vim命令),修改这个文件中 daemonize 的值为yes(默认为no)
  • 在启动redis时, 使用 ./redis-server redis.conf(启动时,指定配置文件)
  • 测试后置启动是否成功:
ps aux|grep redis

Redis 是国产 redisem什么牌子_spring_02

Redis文件介绍
  1. daemonize yes 修改启动方式
  2. port 6379 redis端口
  3. database 16 redis默认开启16个库,也就是16个存储空间来存储数据
  4. cluster-enabled yes 配置redis集群 ,这个配置默认是被注释的,也就是默认不开启集群
  5. save 900 1 这个表示redis的持久化方案 (RDB)
6)dbfilename dump.rdb    redis持久化时,存放数据的文件

 7)appendonly no          是否开启redis的aof 持久化方案

 8) appendfilename “appendonly.aof”  aof持久化方案存放的文件
redis的持久化方案: RDB方案 和 AOF方案

什么是redis的持久化方案
redis 除了可以作为缓存技术,也可以作为非关系型数据库。
作为缓存技术,数据默认是存放在内存中的,(这样可以提升存取速度)
但内存不是持久化设备,不能永久保存数据,一旦机器发生问题,
将会造成数据丢失。因此,redis为了解决这个文件,提供了数据的持久化方 案(memcahe 没有这个能力)

RDB方案:
redis默认开启的一种持久化方案。它会根据时间轴,以及key的数量改变来完成持久化动作。
save 900 1 该备份策略表示 在 900 秒内,如果有一个或多个key的值发生了变化,就触发redis的持久化机制。

AOF方案:
该持久化方案,redis默认情况下没有开启。需要手动开启。
redis.conf 中的 appendonly no 配置成 yes
aof的持久化策略为:redis会记录当前用户执行的,且改变数据的命令。
这种持久化的密度会更细。当然也会对redis的性能产生影响。

注意:即使采用aof的持久化策略,一旦内存崩溃,也会至少丢失一秒的数据

Spring Data Redis入门小Demo

  1. 引入Spring相关依赖、引入JUnit依赖
<properties>
   <spring.version>4.2.4.RELEASE</spring.version>
   <junit.version>4.12</junit.version>
  </properties>
  <dependencies>
    <!-- Spring -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>	
		<version>${spring.version}</version>	
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-beans</artifactId>	
		<version>${spring.version}</version>	
	</dependency>	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>	
		<version>${spring.version}</version>	
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-aspects</artifactId>	
		<version>${spring.version}</version>	
	</dependency>	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context-support</artifactId>	
		<version>${spring.version}</version>	
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>	
		<version>${spring.version}</version>	
	</dependency>	
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>${junit.version}</version>
	</dependency>
  </dependencies>
  1. 引入Jedis和SpringDataRedis依赖
<!-- 缓存 -->
<dependency> 
		  <groupId>redis.clients</groupId> 
		  <artifactId>jedis</artifactId> 
		  <version>2.8.1</version> 
</dependency> 
<dependency> 
		  <groupId>org.springframework.data</groupId> 
		  <artifactId>spring-data-redis</artifactId> 
		  <version>1.7.2.RELEASE</version> 
</dependency>
  1. 在src/main/resources下创建properties文件夹,建立redis-config.properties
redis.host=127.0.0.1 
redis.port=6379 
redis.pass= 
redis.database=0 
redis.maxIdle=300 
redis.maxWait=3000 
redis.testOnBorrow=true
  1. 在src/main/resources下创建spring文件夹 ,创建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">

   <context:property-placeholder location="classpath*:properties/*.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"/>  
   
   <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
     <property name="connectionFactory" ref="JedisConnectionFactory" />  
   </bean>   
</beans>

以上是相关的依赖,具体的后端代码分为几种类型操作

值类型操作
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestValue {
	@Autowired
	private RedisTemplate redisTemplate;	
	@Test
	public void setValue(){
		redisTemplate.boundValueOps("name").set("youjiuye");		
	}	
	@Test
	public void getValue(){
		String str = (String) redisTemplate.boundValueOps("name").get();
		System.out.println(str);
	}	
	@Test
	public void deleteValue(){
		redisTemplate.delete("name");;
	}	
}
Set类型操作
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring/applicationContext-redis.xml")
public class TestSet {
	
	@Autowired
	private RedisTemplate redisTemplate;
	
	/**
	 * 存入值
	 */
	@Test
	public void setValue(){
		redisTemplate.boundSetOps("nameset").add("曹操");		
		redisTemplate.boundSetOps("nameset").add("刘备");	
		redisTemplate.boundSetOps("nameset").add("孙权");
	}
	
	/**
	 * 提取值
	 */
	@Test
	public void getValue(){
		Set members = redisTemplate.boundSetOps("nameset").members();
		System.out.println(members);
	}
	
	/**
	 * 删除集合中的某一个值
	 */
	@Test
	public void deleteValue(){
		redisTemplate.boundSetOps("nameset").remove("孙权");
	}
	
	/**
	 * 删除整个集合
	 */
	@Test
	public void deleteAllValue(){
		redisTemplate.delete("nameset");
	}
}
List类型操作
  • 左压栈
/**
	 * 左压栈:后添加的对象排在前边
	 */
	@Test
	public void testSetValue2(){		
		redisTemplate.boundListOps("namelist2").leftPush("刘备");
		redisTemplate.boundListOps("namelist2").leftPush("关羽");
		redisTemplate.boundListOps("namelist2").leftPush("张飞");		
	}
	
	/**
	 * 显示左压栈集合
	 */
	@Test
	public void testGetValue2(){
		List list = redisTemplate.boundListOps("namelist2").range(0, 10);
		System.out.println(list);
	}

运行结果:
[张飞, 关羽, 刘备]

  • 右压栈
/**
	 * 右压栈:后添加的对象排在后边
	 */
	@Test
	public void testSetValue1(){		
		redisTemplate.boundListOps("namelist1").rightPush("刘备");
		redisTemplate.boundListOps("namelist1").rightPush("关羽");
		redisTemplate.boundListOps("namelist1").rightPush("张飞");		
	}
	
	/**
	 * 显示右压栈集合
	 */
	@Test
	public void testGetValue1(){
		List list = redisTemplate.boundListOps("namelist1").range(0, 10);
		System.out.println(list);
	}

运行结果:
[刘备, 关羽, 张飞]

Hash类型操作 (常使用)
@Test
	public void testSetValue(){
		redisTemplate.boundHashOps("namehash").put("a", "唐僧");
		redisTemplate.boundHashOps("namehash").put("b", "悟空");
		redisTemplate.boundHashOps("namehash").put("c", "八戒");
		redisTemplate.boundHashOps("namehash").put("d", "沙僧");
	}

(2)提取所有的KEY
	@Test
	public void testGetKeys(){
		Set s = redisTemplate.boundHashOps("namehash").keys();		
		System.out.println(s);		
	}

运行结果:
[a, b, c, d]

提取所有的值
	@Test
	public void testGetValues(){
		List values = redisTemplate.boundHashOps("namehash").values();
		System.out.println(values);		
	}

运行结果 [唐僧, 悟空, 八戒, 沙僧]

根据KEY提取值
	@Test
	public void testGetValueByKey(){
		Object object = redisTemplate.boundHashOps("namehash").get("b");
		System.out.println(object);
	}

运行结果 悟空

根据KEY移除值
	@Test
	public void testRemoveValueByKey(){
		redisTemplate.boundHashOps("namehash").delete("c");
	}

现在的集合 [唐僧, 悟空, 沙僧]

(5)高效率存储大量数据
@Test
public void execValue(){

    final List<String> list = new ArrayList<String>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");


    redisTemplate.executePipelined(new SessionCallback<Object>() {
        public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
            for(int i=0;i<list.size();i++){
                redisTemplate.opsForHash().put("list",i,list.get(i));
            }
            return null;
        }
    });

}