1 Redis的安装
1.1 Redis的安装
1 PSFTP连接open 192.168.25.175
,输入用户名密码,上传文件:put C:\Users\Admini\Downloads\redis-3.0.0.tar.gz
2 解压文件:tar -zxvf redis-3.0.0.tar.gz
3 如果没有gcc需要在线安装yum install gcc-c++
,输入gcc
显示no input files
表示安装成功.进入redis目录,查看是否有Makefile文件,输入make
编译
4 安装make install PREFIX=/usr/local/redis
PREFIX参数指定redis的安装目录。一般软件安装到/usr目录下。
1.2 连接redis
前端启动
进入/usr/local/redis/bin
,./redis-server
启动
后端启动
cp ~/redis-3.0.0/redis.conf .
将配置文件拷到当前目录下。修改vim redis.conf
,i
插入修改,Esc后Shift + zz
保存修改并退出编辑器,:q!
退出不保存。将daemonize改为yes。
./redis-server redis.conf
启动redis,ps aux|grep redis
查看进程
Redis-cli
./redis-cli
启动,默认连接localhost运行在6379端口的redis服务,输入ping
返回PONG
,Ctrl + C
退出。
./redis-cli -h 192.168.25.175 -p 6379
启动指定地址及端口的cli
shutdown
关闭redis实例
1.3 Redis命令
String:key-value
set str1 123
添加,get str1
读取,incr / decr 分别加减1
Hash:key-fields-values
hset hash1 field1 abc
添加,hget hash1 field1
读取
设置key的过期时间
ttl str1
查看key的有效期,-1永久,-2不存在
expire key 100
:设置key的过期时间100s
persist key
:清除key的过期时间。Key持久化
keys *
查看所有key
1.4 Redis Desktop Manager
添加连接,可以查看db及其内容

1.5 Redis的持久化方案
Redis的所有数据都是保存到内存中的。
RDB:快照形式,定期把内存中当前时刻的数据保存到磁盘。Redis默认支持的持久化方案。
AOF:append only file。把所有对redis数据库操作的命令,增删改操作的命令。保存到文件中。数据库恢复时把所有的命令执行一遍即可。
2 Jedis
2.1 连接单机版
在content-service项目中,创建测试类TestJedis
@Test
public void testJedis() throws Exception {
// 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
Jedis jedis = new Jedis("192.168.25.153", 6379);
// 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
String result = jedis.get("hello");
// 第三步:打印结果。
System.out.println(result);
// 第四步:关闭Jedis
jedis.close();
}
2.2 连接单机版使用连接池
@Test
public void testJedisPool() throws Exception {
//创建一个数据库连接池对象(单例),需要指定服务的ip和端口号
JedisPool jedisPool = new JedisPool("192.168.25.175", 6379);
//从连接池中获得连接
Jedis jedis = jedisPool.getResource();
//使用Jedis操作数据库(方法级别使用)
String result = jedis.get("jedis-key");
System.out.println(result);
//一定要关闭Jedis连接
jedis.close();
//系统关闭前关闭连接池
jedisPool.close();
}
3 Redis集群的搭建
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点
集群搭建环境
1、使用ruby脚本搭建集群。需要ruby的运行环境。
安装ruby yum install ruby
,yum install rubygems
2、安装ruby脚本运行使用的包,上传redis-3.0.0.gem
,gem install redis-3.0.0.gem
安装,成功后切换到src目录cd redis-3.0.0/src
,寻找rb结尾的ll *.rb
文件redis-trib.rb
,拷贝到cluster目录下cp *.rb /usr/local/redis-cluster
搭建步骤
需要6台redis服务器。搭建伪分布式。需要6个redis实例。需要运行在不同的端口7001-7006
返回/usr/local
,创建目录mkdir redis-cluster
,复制cp -r redis/bin/ redis-cluster/redis01
,进入redis01cd redis-cluster/redis01
,删除数据rm -rf dump.rdb
,修改redis.conf配置文件,端口号7001,把cluster-enabled yes前的注释去掉(输入/cluster-enabled
寻找)。返回,cp -r redis01/ redis02
复制6份。
启动文件,创建vim start-all.sh
,添加权限chmod +x start-all.sh
,然后运行脚本文件
cd redis01
./redis-server redis.conf
cd ..
cd redis02
./redis-server redis.conf
cd ..
...
使用ruby脚本搭建集群./redis-trib.rb create --replicas 1 192.168.25.175:7001 192.168.25.175:7002 192.168.25.175:7003 192.168.25.175:7004 192.168.25.175:7005 192.168.25.175:7006
集群连接
可以用cli连接任意地址,redis01/redis-cli -p 7006 -c
,-c
代表连接的是redis集群。set key1 123
添加key,由于7006是重节点,将会跳到主节点7002

创建关闭集群的脚本
vim shutdow-all.sh
,添加权限 chmod u+x shutdow-all.sh
redis01/redis-cli -p 7001 shutdown
redis01/redis-cli -p 7002 shutdown
redis01/redis-cli -p 7003 shutdown
redis01/redis-cli -p 7004 shutdown
redis01/redis-cli -p 7005 shutdown
redis01/redis-cli -p 7006 shutdown
cluster info
查看集群状态 cluster nodes
查看节点
Jedis连接
@Test
public void testJedisCluster() throws Exception {
//创建一个JedisCluster对象,构造参数Set类型,集合中每个元素是HostAndPort类型
Set<HostAndPort> nodes = new HashSet<>();
//向集合中添加节点
nodes.add(new HostAndPort("192.168.25.175", 7001));
nodes.add(new HostAndPort("192.168.25.175", 7002));
nodes.add(new HostAndPort("192.168.25.175", 7003));
nodes.add(new HostAndPort("192.168.25.175", 7004));
nodes.add(new HostAndPort("192.168.25.175", 7005));
nodes.add(new HostAndPort("192.168.25.175", 7006));
JedisCluster jedisCluster = new JedisCluster(nodes);
//直接使用JedisCluster操作redis,自带连接池。jedisCluster对象可以是单例 的。
jedisCluster.set("cluster-test", "hello jedis cluster");
String string = jedisCluster.get("cluster-test");
System.out.println(string);
//系统关闭前关闭JedisCluster
jedisCluster.close();
}
4 向业务逻辑中添加缓存
4.1 接口封装
常用的操作redis的方法提取出一个接口,分别对应单机版和集群版创建两个实现类。采用策略者模式。
接口定义
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);
}
分别创建单机版与集群版实现类
创建配置文件applicationContext-redis.xml,由于applicationContext-service.xml配置中<context:component-scan base-package="com.taotao.content.service"/>
扫描包的同时开启了注解,因此<context:annotation-config/>
可以不用配置,但在测试中由于不加载applicationContext-service.xml,因此需要加此配置,否则实现类中@Autowired
无法识别。注意:单机版和集群版不能共存,使用单机版时注释集群版的配置。使用集群版,把单机版注释。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
...>
<context:annotation-config/>
<!-- redis单机版 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.175"/>
<constructor-arg name="port" value="6379"/>
</bean>
<bean id="jedisClientPool" class="com.taotao.jedis.JedisClientPool"/>
<!-- 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.25.153"/>
<constructor-arg name="port" value="7001"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"/>
<constructor-arg name="port" value="7002"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"/>
<constructor-arg name="port" value="7003"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"/>
<constructor-arg name="port" value="7004"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"/>
<constructor-arg name="port" value="7005"/>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.153"/>
<constructor-arg name="port" value="7006"/>
</bean>
</set>
</constructor-arg>
</bean>
<bean id="jedisClientCluster" class="com.taotao.jedis.JedisClientCluster"/> -->
</beans>
使用单机版时,进入redis/bin,./redis-server redis.conf
启动,添加测试方法
@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", "100");
String result = jedisClient.get("first");
System.out.println(result);
}
测试集群版时,将applicationContext-service.xml配置成集群模式,测试代码不用修改。
4.2 添加缓存
功能分析
查询内容列表时添加缓存。
1、查询数据库之前先查询缓存。
2、查询到结果,直接响应结果。
3、查询不到,缓存中没有需要查询数据库。
4、把查询结果添加到缓存中。
5、返回结果。
向redis中添加缓存:
key:cid
value:内容列表。需要把java对象转换成json。
使用hash对key进行归类。
查询数据
首先查询缓存,若有则直接返回,从数据库读取后,向缓存添加数据。
@Override
public List<TbContent> getContentList(long cid) {
//查询缓存
try {
String json = jedisClient.hget(CONTENT_KEY, cid + "");
//判断json是否为空
if (StringUtils.isNotBlank(json)) {
//把json转换成list
List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
return list;
}
} catch (Exception e) {
e.printStackTrace();
}
//根据cid查询内容列表
TbContentExample example = new TbContentExample();
//设置查询条件
Criteria criteria = example.createCriteria();
criteria.andCategoryIdEqualTo(cid);
//执行查询
List<TbContent> list = contentMapper.selectByExample(example);
//向缓存中添加数据
try {
jedisClient.hset(CONTENT_KEY, cid + "", JsonUtils.objectToJson(list));
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
缓存同步
对内容信息做增删改操作后只需要把对应缓存删除即可,根据cid删除。
@Override
public TaotaoResult addContent(TbContent content) {
//补全属性
content.setCreated(new Date());
content.setUpdated(new Date());
//插入数据
contentMapper.insert(content);
//缓存同步
jedisClient.hdel(CONTENT_KEY, content.getCategoryId().toString());
return TaotaoResult.ok();
网友评论