一、说在前面的话

前面几节我们主要对该项目的后端进行了增删改查,但是所有的数据都是存放在数据库中,这样的话数据库的压力显而易见是很大的,因此本节学习nosql的缓存,也就是redis的使用,在使用之前,我们来想一想为什么要用redis、redis的内存是否有限制,redis的存储方式。那么让我们带着这些问题去学习redis。

Redis服务器的搭建和使用。

二、redis

1、redis的安装

Redis是c语言开发的。

安装redis需要c语言的编译环境。如果没有gcc需要在线安装。(上一节nginx也是c开发的,因此也安装了c++编译环境)

yum install gcc-c++

安装步骤:

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

第二步:解压缩redis。

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

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

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

2、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/ == (为了启动的后面直接跟配置文件)

修改配置文件:daemonize: yes

daemonize:yes:

redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。

daemonize:no:

当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。

老版本默认是no,新版本现在默认是yes。

最后我们启动的时候在后面跟上配置文件即可

[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

3、redis的命令行连接和图形化连接

a、命令连接

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

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

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

-h:连接的服务器的地址(host)

-p:服务的端口号(port)

b、图形化连接

使用软件RedisDesktopManager进行连接redis





c、redis的存储数据类型

redis有5中存储数据类型,每一种类型的数据都以String的形式进行保存到redis缓存中的。

——1、String:key-value(做缓存、可以使用ttl过期时间,因此经常被用到用户登录、商品缓存(使用TTL有效的使热门数据存放到redis缓存中,从而避免内存浪费的可能。)、订单提交等模块中)故经常使用

get、set、

incr:加一(生成id)

Decr:减一



当然只有value为数值才可以增减,若为字母,则报错



接下来看看图形化界面是什么样的?



——2、Hash:key-fields-values(做缓存)也经常使用(这里因为hash没法使用ttl过期,所以一般用在用户的购物车等模块中。)

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

使用hash对key进行归类。

Hset:向hash中添加内容

Hget:从hash中取内容



在图形化界面我们再看看什么样的



3、list 有顺序可重复

lrange list1 0 -1 代表输出list1集合,从第0个开始,一直到最后一个(0代表第一个、-1代表最后一个)。

192.168.25.153:6379> lpush list1 a b c d
(integer) 4
192.168.25.153:6379> lrange list1 0 -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"

4、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"

5、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"

d、key命令(不可以对hash的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



只能对整个hash设置过期时间。



消除key的过期时间:

PERSIST hstr

6、redis在项目中的使用

我们在项目需要使用到redis,那么我们该如何去连接呢,redis给我们提供了连接的jar包jedis,我们需要把它引入到其中,添加依赖。建议添加到服务层中。

由于redis含有单机版和集群版(集群版搭建链接),因此这里创建了一个接口,把单机版和集群版都实现这个接口(JedisClient ),若我们使用单机版,则在配置文件中配置单机版的设置,反之配置集群版的设置。单机版的实现类和集群版的实现类内容不一样。但是我们都是基于接口进行操作的。这样的话开发和上线就不需要更换代码了,只需要将配置文件单机版和集群版修改即可。

JedisClient 接口:

package cn.tsu.e3mall.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);
}

JedisClientPool(单机版)

单机版的获取Pool后,需要getResource,然后就可以得到jedis,就可以操作set,get命令。

package cn.tsu.e3mall.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;
} }

JedisClientCluster(集群版)JedisClientCluster可以直接set、get

package cn.tsu.e3mall.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);
}
}

applicationContext-redis.xml关于redis的配置文件:

<?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:dubbo="http://code.alibabatech.com/schema/dubbo" 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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 1、搭建单机版redis -->
<bean id="jedisClientPool" class="cn.tsu.e3mall.jedis.JedisClientPool">
<property name="jedisPool" ref="jedisPool" />
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.110" />
<constructor-arg name="port" value="6379" />
</bean> <!--2、搭建集群版redis -->
<!-- <bean id="jedisClientCluster" class="cn.tsu.e3mall.jedis.JedisClientCluster">
<property name="jedisCluster" ref="jedisCluster" />
</bean>
<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.110" />
<constructor-arg name="port" value="7001" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.110" />
<constructor-arg name="port" value="7002" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.110" />
<constructor-arg name="port" value="7003" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.110" />
<constructor-arg name="port" value="7004" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.110" />
<constructor-arg name="port" value="7005" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.25.110" />
<constructor-arg name="port" value="7006" />
</bean>
</set>
</constructor-arg>
</bean> -->
</beans>

service层:(首页大广告的缓存(应该内容很少,故设置为永存,无TTL过期时间))

业务逻辑:

先从缓存中查询,若有返回数据

若缓存中没有,则去数据库查询,

然后再保存到缓存中。

添加缓存不能影响正常的逻辑,

因此都需要try{} catch()

// 首页回显广告
@Override
public List<TbContent> findad1List(Long category_id) {
try {
//先从redis中调取
String jsonlist = jedisClient.hget(Commons.CONTENT_LIST, category_id+"");
if (jsonlist !=null ) {
List<TbContent> list = JsonUtils.jsonToList(jsonlist, TbContent.class);
return list;
}
} catch (Exception e) {
e.printStackTrace();
}
TbContentExample example = new TbContentExample();
example.createCriteria().andCategoryIdEqualTo(category_id);
List<TbContent> list = contentMapper.selectByExample(example);
try {
jedisClient.hset(Commons.CONTENT_LIST, category_id+"", JsonUtils.objectToJson(list));
} catch (Exception e) {
e.printStackTrace();
}
return list;
}

controller层:

	@Controller
public class ContentController {
@Autowired
private ContentService contentService;
@RequestMapping("/index")
public String showIndex(Model model) {
//回显大广告
List<TbContent> ad1list = contentService.findad1List(89l);
model.addAttribute("ad1List", ad1list);
return "index";
}
}

最新文章

  1. PCA与LDA的区别与联系
  2. LTE 测试文档(翻译)
  3. python学习笔记六 面向对象相关下(基础篇)
  4. IOS之UI--小实例项目--添加商品和商品名
  5. 【读书笔记】读《JavaScript设计模式》之代理模式
  6. ELK-Python(一)
  7. 分享第一次使用ProcessOn心得
  8. Linux CPU亲缘性详解
  9. [转] 小tip: 使用CSS将图片转换成模糊(毛玻璃)效果 ---张鑫旭
  10. Embedded Linux Primer----嵌入式Linux基础教程--导论
  11. webpack dev server 和 sublime text 配合时需要注意的地方
  12. MyBatis的增删改查。
  13. jsonModel使用
  14. Jmeter连接数据库方式
  15. (转)Thinkpad X1 Carbon 扩展硬盘
  16. C++ 语法--变量和常量
  17. RefreshListView下拉刷新
  18. Go Example--定时器
  19. 第28次Scrum会议(11/16)【欢迎来怼】
  20. 模块的封装之C语言类的继承和派生

热门文章

  1. 无版号的ios手游下架 TF签名才是正确选择?
  2. Android常用布局和控件
  3. javascript Math对象 、Date对象笔记
  4. Weblogic 连接 RMI 服务报错 Connection refused
  5. idea的yml文件不识别问题
  6. Eclipse工具的简单使用
  7. LInux回顾与Shell编程
  8. OpenCV常用图像拼接方法(一) :直接拼接
  9. flask-sqlalchemy同字段多条件过滤
  10. 串口线接Linux设备U盘安装系统和直接安装设备接显示屏2种方式不同