e3mall商城的归纳总结6之redis
一、说在前面的话
前面几节我们主要对该项目的后端进行了增删改查,但是所有的数据都是存放在数据库中,这样的话数据库的压力显而易见是很大的,因此本节学习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";
}
}
最新文章
- PCA与LDA的区别与联系
- LTE 测试文档(翻译)
- python学习笔记六 面向对象相关下(基础篇)
- IOS之UI--小实例项目--添加商品和商品名
- 【读书笔记】读《JavaScript设计模式》之代理模式
- ELK-Python(一)
- 分享第一次使用ProcessOn心得
- Linux CPU亲缘性详解
- [转] 小tip: 使用CSS将图片转换成模糊(毛玻璃)效果 ---张鑫旭
- Embedded Linux Primer----嵌入式Linux基础教程--导论
- webpack dev server 和 sublime text 配合时需要注意的地方
- MyBatis的增删改查。
- jsonModel使用
- Jmeter连接数据库方式
- (转)Thinkpad X1 Carbon 扩展硬盘
- C++ 语法--变量和常量
- RefreshListView下拉刷新
- Go Example--定时器
- 第28次Scrum会议(11/16)【欢迎来怼】
- 模块的封装之C语言类的继承和派生