什么是redis
典型的NoSql数据库服务器,在很多时候,人们只是将Redis视为Key/Value数据库服务器,然而事实并非如此,在目前的版本中,Redis除了Key/Value之外还支持List、Hash、Set和Ordered Set等数据结构,因此它的用途也更为宽泛。通常的用法就是将数据存放到内存到,由于内存存取速度快,官方称读取速度会达到30万次每秒,写速度在10万次每秒,所以redis被广泛应用在互联网项目中。
为什么使用redis
主要是性能和并发,以及在同类型产品中的优势。
A、对于性能来说,最好标准就是用户的良好体验,而用户的的良好体验最重要的就是请求是否可以迅速响应。这就要求数据库有良好的响应能力。当把需要不断请求且结果不频繁变动的sql,放到redis缓冲中,然后请求去缓冲中读取数据,就可以实现快速响应。
B、对于并发来说,在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问数据库。
C、和redis最相似的memcached,memcached只是单纯的key-value数据库,且没有提供任何数据持久化的功能,数据缓冲服务一旦宕机,服务器中的数据全部丢失。而redis在这两点上,都由于memcached,redis除了支持key-value外,还支持List、Hash、Set和Ordered Set等数据结构,而且redis还提供了两种持久化的方式:RDB和AOF。
使用例子
项目中的首页信息要存放在Redis中,因为访问频率高,允许有缓存的数据。;
redis单机版安装
第一步:安装gcc编译环境:yum install gcc-c++
第二步:把redis的源码上传到linux服务器。
第三步:解压缩。:tar -zxvf redis-3.0.0.tar.gz
第四步:make
第五步:make install PREFIX=/usr/local/
第六步:启动redis: ./redis-server redis.conf;启动前需要修改配置文件,将daemonize改为yes;
单机版测试
//使用连接池
@Test
public void testJedisPool() throws Exception {
//创建一个连接池对象
//系统中应该是单例的。
JedisPool jedisPool = new JedisPool("192.168.128.111", 6379);
//从连接池中获得一个连接
Jedis jedis = jedisPool.getResource();
jedis.set("test", "hello jedis");
String result = jedis.get("test");
System.out.println(result);
//jedis必须关闭
jedis.close();
//系统关闭时关闭连接池
jedisPool.close();
}
如果测试的时候出现请求超时的错误:
只要关闭centos防火墙,便可搞定:systemctl stop firewalld.service
redis集群版部署
集群中应该至少有三个节点,每个节点有一备份节点。需要6台服务器。
搭建伪分布式,需要6个redis实例。
搭建集群的步骤:
第一步:创建6个redis实例指定端口从7001到7006
第二步:修改redis.conf 打开Cluster-enable yes前面的注释。
第三步:需要一个ruby脚本。在redis源码文件夹下的src目录下。redis-trib.rb
第四步:把redis-trib.rb文件复制到到redis-cluster目录下。
第五步:执行ruby脚本之前,需要安装ruby环境。
1、yum install ruby
2、yum install rubygems
3、安装redis-trib.rb运行依赖的ruby的包: gem install redis-3.0.0.gem
第六步:用脚本启动所有的redis实例。
第七步:使用redis-trib.rb创建集群,执行以下命令
./redis-trib.rb create --replicas 1 192.168.128.111:7001 192.168.128.111:7002 192.168.128.111:7003
192.168.128.111:7004 192.168.128.111:7005 192.168.128.111:7006
集群版测试
//连接redis集群
@Test
public void testJedisCluster() throws Exception {
//创建一个JedisCluster对象
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.128.111", 7001));
nodes.add(new HostAndPort("192.168.128.111", 7002));
nodes.add(new HostAndPort("192.168.128.111", 7003));
nodes.add(new HostAndPort("192.168.128.111", 7004));
nodes.add(new HostAndPort("192.168.128.111", 7005));
nodes.add(new HostAndPort("192.168.128.111", 7006));
//在nodes中指定每个节点的地址
//jedisCluster在系统中是单例的。
JedisCluster jedisCluster = new JedisCluster(nodes);
jedisCluster.set("name", "zhangsan");
jedisCluster.set("value", "100");
String name = jedisCluster.get("name");
String value = jedisCluster.get("value");
System.out.println(name);
System.out.println(value);
//系统关闭时关闭jedisCluster
jedisCluster.close();
}
项目中使用jedis
单机版实现类
/**
* redis客户端单机版实现类
* <p>Title: JedisClientSingle</p>
* @author 吕德彪
* @date 2018年8月24日 10:49:53 * @version 1.0
*/
public class JedisClientSingle implements JedisClient{
@Autowired
private JedisPool jedisPool;
@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
}
@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
//HSet:将哈希表key中域field设置成指定的value
@Override
public Long hset(String key, String item, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, item, value);
jedis.close();
return result;
}
//HGet:返回哈希表key中给定field的值
@Override
public String hget(String key, String item) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, item);
jedis.close();
return result;
}
//incr递增1并返回递增后的结果;
@Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
}
//decr递减1并返回递减后的结果;
@Override
public Long decr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.decr(key);
jedis.close();
return result;
}
//为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
@Override
public Long expire(String key, int second) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, second);
jedis.close();
return result;
}
//以秒为单位,返回给定 key 的剩余生存时间
@Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
}
}
集群版实现类
/**
* redis客户端集群版实现类
* <p>Title: JedisClientCluster</p>
* @author 吕德彪
* @date 2018年8月24日 10:51:09
* @version 1.0
*/
public class JedisClientCluster implements JedisClient {
@Autowired
private JedisCluster jedisCluster;
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
@Override
public Long hset(String key, String item, String value) {
return jedisCluster.hset(key, item, value);
}
@Override
public String hget(String key, String item) {
return jedisCluster.hget(key, item);
}
@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}
@Override
public Long decr(String key) {
return jedisCluster.decr(key);
}
@Override
public Long expire(String key, int second) {
return jedisCluster.expire(key, second);
}
@Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
}
}
Spring的配置
单机版和集群版配置不能同时存在,使用单机版时需要把集群版注释掉,使用集群版需要把单机版注释掉。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 包扫描器,扫描带@Service注解的类 -->
<context:component-scan base-package="com.taotao.rest.service"></context:component-scan>
<!-- 配置redis客户端单机版 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.128.111"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<!-- 配置redis客户端实现类 -->
<bean id="jedisClientSingle" class="com.taotao.rest.component.impl.JedisClientSingle"/>
<!-- 配置redis客户端集群版 -->
<!-- <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg>
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.128.111"/>
<constructor-arg name="port" value="7001"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.128.111"/>
<constructor-arg name="port" value="7002"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.128.111"/>
<constructor-arg name="port" value="7003"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.128.111"/>
<constructor-arg name="port" value="7004"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.128.111"/>
<constructor-arg name="port" value="7005"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.128.111"/>
<constructor-arg name="port" value="7006"/>
</bean>
</set>
</constructor-arg>
</bean>
<bean id="jedisClientCluster" class="com.taotao.rest.component.impl.JedisClientCluster"/> -->
</beans>
测试
@Test
public void testJedisClientSpring() throws Exception {
//创建一个spring容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");
//从容器中获得JedisClient对象
JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
//jedisClient操作redis
jedisClient.set("cliet1", "1000");
String string = jedisClient.get("cliet1");
System.out.println(string);
}
结语
在项目中使用的时候,可以将单机版实现类和集群版实现类以及读取配置文件都封装在工具类中,然后调用工具类,使用相应的方法即可。