1.学习计划

1、Redis服务器搭建

2、Redis持久化

3、Redis集群搭建

4、Jedis

5、Solr服务器安装

2.Redis的安装

2.1. Redis的安装

Redis是c语言开发的。

安装redis需要c语言的编译环境。如果没有gcc需要在线安装。yum install gcc-c++

安装步骤:

第一步:redis的源码包上传到linux系统。

第二步:解压缩redis。

第三步:编译。进入redis源码目录。make

第四步:安装。make install PREFIX=/usr/local/redis

PREFIX参数指定redis的安装目录。一般软件安装到/usr目录下

2.2. 连接redis

2.2.1.    redis的启动:

前端启动:在redis的安装目录下直接启动redis-server

[root@localhost bin]# ./redis-server

后台启动:

把/root/redis-3.0.0/redis.conf复制到/usr/local/redis/bin目录下

[root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/

修改配置文件:

[root@localhost bin]# ./redis-server redis.conf

查看redis进程:

[root@localhost bin]# ps aux|grep redis

root      5190  0.1  0.3  33936  1712 ?        Ssl  18:23   0:00 ./redis-server *:6379

root      5196  0.0  0.1   4356   728 pts/0    S+   18:24   0:00 grep redis

2.2.2.    Redis-cli

[root@localhost bin]# ./redis-cli

默认连接localhost运行在6379端口的redis服务。

[root@localhost bin]# ./redis-cli -h 192.168.25.153 -p 6379

-h:连接的服务器的地址

-p:服务的端口号

关闭redis:[root@localhost bin]# ./redis-cli shutdown

2.3. Redis五种数据类型

String:key-value(做缓存)

Redis中所有的数据都是字符串。命令不区分大小写,key是区分大小写的。Redis是单线程的。Redis中不适合保存内容大的数据。

get、set、

incr:加一(生成id)

Decr:减一

Hash:key-fields-values(做缓存)

相当于一个key对于一个map,map中还有key-value

使用hash对key进行归类。

Hset:向hash中添加内容

Hget:从hash中取内容

List:有顺序可重复

192.168.25.153:6379> lpush list1 a b c d

(integer) 4

192.168.25.153:6379> lrange list1 0 -1(-1显示所有)

1) "d"

2) "c"

3) "b"

4) "a"

192.168.25.153:6379> rpush list1 1 2 3 4

(integer) 8

192.168.25.153:6379> lrange list1 0 -1

1) "d"

2) "c"

3) "b"

4) "a"

5) "1"

6) "2"

7) "3"

8) "4"

192.168.25.153:6379>

192.168.25.153:6379> lpop list1

"d"

192.168.25.153:6379> lrange list1 0 -1

1) "c"

2) "b"

3) "a"

4) "1"

5) "2"

6) "3"

7) "4"

192.168.25.153:6379> rpop list1

"4"

192.168.25.153:6379> lrange list1 0 -1

1) "c"

2) "b"

3) "a"

4) "1"

5) "2"

6) "3"

192.168.25.153:6379>

Set:元素无顺序,不能重复

192.168.25.153:6379> sadd set1 a b c c c d

(integer) 4

192.168.25.153:6379> smembers set1

1) "b"

2) "c"

3) "d"

4) "a"

192.168.25.153:6379> srem set1 a

(integer) 1

192.168.25.153:6379> smembers set1

1) "b"

2) "c"

3) "d"

192.168.25.153:6379>

还有集合运算命令,自学。

SortedSet(zset):有顺序,不能重复

192.168.25.153:6379> zadd zset1 2 a 5 b 1 c 6 d

(integer) 4

192.168.25.153:6379> zrange zset1 0 -1

1) "c"

2) "a"

3) "b"

4) "d"

192.168.25.153:6379> zrem zset1 a

(integer) 1

192.168.25.153:6379> zrange zset1 0 -1

1) "c"

2) "b"

3) "d"

192.168.25.153:6379> zrevrange zset1 0 -1

1) "d"

2) "b"

3) "c"

192.168.25.153:6379> zrange zset1 0 -1 withscores

1) "c"

2) "1"

3) "b"

4) "5"

5) "d"

6) "6"

192.168.25.153:6379> zrevrange zset1 0 -1 withscores

1) "d"

2) "6"

3) "b"

4) "5"

5) "c"

6) "1"

192.168.25.153:6379>

2.4. Key命令

设置key的过期时间。

Expire key second:设置key的过期时间

Ttl key:查看key的有效期

Persist key:清除key的过期时间。Key持久化。

192.168.25.153:6379> expire Hello 100

(integer) 1

192.168.25.153:6379> ttl Hello

(integer) 77

3.   Redis的持久化方案

Redis的所有数据都是保存到内存中的。

Rdb:快照形式,定期把内存中当前时刻的数据保存到磁盘。Redis默认支持的持久化方案。

aof形式:append only file。把所有对redis数据库操作的命令,增删改操作的命令。保存到文件中。数据库恢复时把所有的命令执行一遍即可。

在redis.conf配置文件中配置。

Rdb:

Aof的配置:

两种持久化方案同时开启使用aof文件来恢复数据库。

4.   Redis集群的搭建

4.1. redis-cluster架构图

redis-cluster投票:容错

4.2. Redis集群的搭建

Redis集群中至少应该有三个节点。要保证集群的高可用,需要每个节点有一个备份机。

Redis集群至少需要6台服务器。

搭建伪分布式。可以使用一台虚拟机运行6个redis实例。需要修改redis的端口号7001-7006

4.2.1.    集群搭建环境

1、使用ruby脚本搭建集群。需要ruby的运行环境。

安装ruby

yum install ruby

yum install rubygems

2、安装ruby脚本运行使用的包。

[root@localhost heima]# gem install redis-3.0.0.gem

4.2.2.    搭建步骤

第一步:创建6个redis实例,每个实例运行在不同的端口。需要修改redis.conf配置文件。配置文件中还需要把cluster-enabled yes前的注释去掉。

进入/usr/local目录下创建目录redis-cluster

[root@localhost local]# mkdir redis-cluster

[root@localhost local]# cp redis/bin redis-cluster/redis01 -r

删除redis01下面的dump.rdb和appendonly.aof

[root@localhost redis01]# rm -f dump.rdb

[root@localhost redis01]# vim redis.conf

cluster-enabled yes注释去掉和修改port为7001

复制redis01

[root@localhost redis-cluster]# cp -r redis01 /redis02
[root@localhost redis-cluster]# cp -r redis01 /redis03
[root@localhost redis-cluster]# cp -r redis01 /redis04
[root@localhost redis-cluster]# cp -r redis01 /redis05
[root@localhost redis-cluster]# cp -r redis01 /redis06

修改redis.conf文件

修改每个redis下的port为7002-7006

第二步:启动每个redis实例。

[root@localhost redis-cluster]# vim start-all.sh

cd redis01
./redis-server redis.conf
cd ..
cd redis02
./redis-server redis.conf
cd ..
cd redis03
./redis-server redis.conf
cd ..
cd redis04
./redis-server redis.conf
cd ..
cd redis05
./redis-server redis.conf
cd ..
cd redis06
./redis-server redis.conf
cd ..

-rw-r--r-- 1 root root  258 Nov 29 22:24 start-all.sh(修改权限)

[root@localhost redis-cluster]# chmod u+x start-all.sh

[root@localhost redis-cluster]# ./start-all.sh

第三步:使用ruby脚本搭建集群。

[root@localhost src]# cp redis-trib.rb /usr/local/redis-cluster/

[root@localhost redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.25.128:7001 192.168.25.128:7002 192.168.25.128:7003 192.168.25.128:7004 192.168.25.128:7005 192.168.25.128:7006

4.3. 集群的使用方法

[root@localhost redis-cluster]# redis01/redis-cli -p 7004  -c

5.   Jedis

需要把jedis依赖的jar包添加到工程中。Maven工程中需要把jedis的坐标添加到依赖。

添加到服务层。E3-content-Service工程中。

5.1. 连接单机版

第一步:创建一个Jedis对象。需要指定服务端的ip及端口。

第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。

第三步:打印结果。

第四步:关闭Jedis

    @Test
public void testJedis() throws Exception{
// 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
Jedis jedis = new Jedis("192.168.25.128", 6379);
// 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
jedis.set("hello","this is me");
String result = jedis.get("hello");
// 第三步:打印结果。
System.out.println(result);
// 第四步:关闭Jedis
jedis.close(); }

5.2. 连接单机版使用连接池

第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。

第二步:从JedisPool中获得Jedis对象。

第三步:使用Jedis操作redis服务器。

第四步:操作完毕后关闭jedis对象,连接池回收资源。

第五步:关闭JedisPool对象。

    @Test
public void testJedisPool() throws Exception {
// 第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。
JedisPool jedisPool = new JedisPool("192.168.25.128", 6379);
// 第二步:从JedisPool中获得Jedis对象。
Jedis jedis = jedisPool.getResource();
// 第三步:使用Jedis操作redis服务器。
jedis.set("jedis", "test111");
String result = jedis.get("jedis");
System.out.println(result);
// 第四步:操作完毕后关闭jedis对象,连接池回收资源。
jedis.close();
// 第五步:关闭JedisPool对象。
jedisPool.close();
}

5.3. 连接集群版

第一步:使用JedisCluster对象。需要一个Set<HostAndPort>参数。Redis节点的列表。

第二步:直接使用JedisCluster对象操作redis。在系统中单例存在。

第三步:打印结果

第四步:系统关闭前,关闭JedisCluster对象。

    @Test
public void testJedisCluster() throws Exception {
// 第一步:使用JedisCluster对象。需要一个Set<HostAndPort>参数。Redis节点的列表。
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.25.128", 7001));
nodes.add(new HostAndPort("192.168.25.128", 7002));
nodes.add(new HostAndPort("192.168.25.128", 7003));
nodes.add(new HostAndPort("192.168.25.128", 7004));
nodes.add(new HostAndPort("192.168.25.128", 7005));
nodes.add(new HostAndPort("192.168.25.128", 7006));
JedisCluster jedisCluster = new JedisCluster(nodes);
// 第二步:直接使用JedisCluster对象操作redis。在系统中单例存在。
jedisCluster.set("hello", "100");
String result = jedisCluster.get("hello");
// 第三步:打印结果
System.out.println(result);
// 第四步:系统关闭前,关闭JedisCluster对象。
jedisCluster.close();
}

6.   向业务逻辑中添加缓存

6.1. 接口封装

常用的操作redis的方法提取出一个接口,分别对应单机版和集群版创建两个实现类。(建在common工程下)

6.1.1.    接口定义

package cn.e3mall.common.jedis;

import java.util.List;

public interface JedisClient {

    String set(String key, String value);
String get(String key);
Boolean exists(String key);
Long expire(String key, int seconds);
Long ttl(String key);
Long incr(String key);
Long hset(String key, String field, String value);
String hget(String key, String field);
Long hdel(String key, String... field);
Boolean hexists(String key, String field);
List<String> hvals(String key);
Long del(String key);
}

6.1.2.    单机版实现类

package cn.e3mall.common.jedis;

import java.util.List;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool; public class JedisClientPool implements JedisClient { private JedisPool jedisPool; public JedisPool getJedisPool() {
return jedisPool;
} public void setJedisPool(JedisPool jedisPool) {
this.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;
} @Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
} @Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
} @Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
} @Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
} @Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
} @Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
} @Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
} @Override
public Boolean hexists(String key, String field) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.hexists(key, field);
jedis.close();
return result;
} @Override
public List<String> hvals(String key) {
Jedis jedis = jedisPool.getResource();
List<String> result = jedis.hvals(key);
jedis.close();
return result;
} @Override
public Long del(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.del(key);
jedis.close();
return result;
} }

配置:applicationContext-redis.xml

<?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.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <!-- 连接redis单机版 -->
<bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool">
<property name="jedisPool" ref="jedisPool"></property>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.128"/>
<constructor-arg name="port" value="6379"/>
</bean>
</beans>

6.1.3.    集群版实现类

package cn.e3mall.common.jedis;

import java.util.List;

import redis.clients.jedis.JedisCluster;

public class JedisClientCluster implements JedisClient {

    private JedisCluster jedisCluster;

    public JedisCluster getJedisCluster() {
return jedisCluster;
} public void setJedisCluster(JedisCluster jedisCluster) {
this.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 Boolean exists(String key) {
return jedisCluster.exists(key);
} @Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
} @Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
} @Override
public Long incr(String key) {
return jedisCluster.incr(key);
} @Override
public Long hset(String key, String field, String value) {
return jedisCluster.hset(key, field, value);
} @Override
public String hget(String key, String field) {
return jedisCluster.hget(key, field);
} @Override
public Long hdel(String key, String... field) {
return jedisCluster.hdel(key, field);
} @Override
public Boolean hexists(String key, String field) {
return jedisCluster.hexists(key, field);
} @Override
public List<String> hvals(String key) {
return jedisCluster.hvals(key);
} @Override
public Long del(String key) {
return jedisCluster.del(key);
} }

Spring的配置:

    <!-- 集群版的配置 -->
<bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster">
<property name="jedisCluster" ref="jedisCluster"/>
</bean>
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.128"></constructor-arg>
<constructor-arg name="port" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
</bean>

注意:单机版和集群版不能共存,使用单机版时注释集群版的配置。使用集群版,把单机版注释。

6.2. 封装代码测试

    @Test
public void testJedisClient() throws Exception {
//初始化Spring容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
//从容器中获得JedisClient对象
JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
jedisClient.set("first", "1000000000000");
String result = jedisClient.get("first");
System.out.println(result); }

6.3. 添加缓存

6.3.1.    功能分析

查询内容列表时添加缓存。

1、查询数据库之前先查询缓存。

2、查询到结果,直接响应结果。

3、查询不到,缓存中没有需要查询数据库。

4、把查询结果添加到缓存中。

5、返回结果。

向redis中添加缓存:

Key:cid

Value:内容列表。需要把java对象转换成json。

使用hash对key进行归类。

HASH_KEY:HASH

|--KEY:VALUE

|--KEY:VALUE

|--KEY:VALUE

|--KEY:VALUE

注意:添加缓存不能影响正常业务逻辑。

6.3.2.    代码实现

           @Autowired
private JedisClient jedisClient; @Value("${CONTENT_LIST}")
private String CONTENT_LIST;
@Override
public List<TbContent> getContentListByCid(Long cid) {
//查询缓存
try {
String json = jedisClient.hget(CONTENT_LIST, cid + "");
//判断json是否为空
if (StringUtils.isNotBlank(json)) {
//把json转换成list
List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
return list;
}
} catch (Exception e) {
e.printStackTrace();
} TbContentExample example = new TbContentExample();
Criteria criteria = example.createCriteria();
criteria.andCategoryIdEqualTo(cid);
List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example); //向缓存中添加数据
try {
jedisClient.hset(CONTENT_LIST, cid + "", JsonUtils.objectToJson(list));
} catch (Exception e) {
e.printStackTrace();
} return list;
}

resource.properties

CONTENT_LIST=CONTENT_LIST

添加配置到applicationContext-dao.xml文件中

6.4. 缓存同步

对内容信息做增删改操作后只需要把对应缓存删除即可。

可以根据cid删除。

    @Override
public E3Result addContent(TbContent content) {
//补全属性
content.setCreated(new Date());
content.setUpdated(new Date());
//插入数据
contentMapper.insert(content);
//缓存同步
jedisClient.hdel(CONTENT_LIST, content.getCategoryId().toString()); return E3Result.ok();
}

最新文章

  1. STL string的构造函数
  2. C# MDI子窗体互相操作
  3. JSTL(fn函数)
  4. PHP学习笔记二十九【接口】
  5. mysql建库
  6. 从零开始学习Vue(三)
  7. springmvc返回值为void
  8. Eclipse插件springsource-tool-suite在线和离线安装步骤
  9. django三种文件下载方式
  10. SpriteBuilder中如何简单的重置APP保存的数据
  11. ubunut在系统恢复模式下无法修改root密码的分析和解决
  12. Executors的四种线程池
  13. Spring Boot 主类及目录结构介绍
  14. opencv imdecode和imencode用法
  15. 多网卡环境下Eureka服务注册IP选择问题
  16. Ribbon 常用配置
  17. 修改maven项目的编译版本
  18. 用plsql 导入导出oracle表结构数据
  19. git设置ss代理
  20. PyCharm配置SFTP远程调试Django应用

热门文章

  1. Linux学习之路——文件查找:find
  2. python:用wordcloud生成一个文本的词云
  3. docker-compose 安装redis sentinel,共享主机网络模式
  4. git初始化本地项目及关联github远程库
  5. 高分辨率下放大netbeans中的小图标
  6. mysql 插入更新判断 ON DUPLICATE KEY UPDATE 和 REPLACE INTO
  7. 涂抹mysql笔记-数据备份和恢复
  8. HTML span标签:用来组合文档中的行内元素
  9. day32基于tcp协议的远程执行命令
  10. python初接触