1. Redis 介绍
Redis 是一种非关系型数据库(NoSQL),NoSQL 是以 key-value 的形式存储的,和传统的关系型数据库不一样,不一定遵循传统数据库的一些基本要求,比如说 SQL 标准,ACID 属性,表结构等等,这类数据库主要有以下特点:非关系型的、分布式的、开源的、水平可扩展的。 NoSQL 使用场景有:对数据高并发读写、对海量数据的高效率存储和访问、对数据的高可扩展性和高可用性等等。 Redis 的 key 可以是字符串、哈希、链表、集合和有序集合。value 类型很多,包括 String、list、set、zset。这些数据类型都支持 push/pop、add/remove、取交集和并集以及更多更丰富的操作,Redis 也支持各种不同方式的排序。为了保证效率,数据都是在缓存在内存中,它也可以周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中。 有了 redis 有哪些好处呢?举个比较简单的例子:
Redis 集群和 Mysql 是同步的,首先会从 redis 中获取数据,如果 redis 挂了,再从 mysql 中获取数据,这样网站就不会挂掉。更多关于 redis 的介绍以及使用场景,可以谷歌和百度,在这就不赘述了。
2. Redis 安装
本课程是在 vmvare 虚拟机中来安装的 redis (centos 7),学习的时候如果有自己的阿里云服务器,也可以在阿里云中来安装 redis,都可以。只要能 ping 的通云主机或者虚拟机的 ip,然后在虚拟机或者云主机中放行对应的端口(或者关掉防火墙)即可访问 redis。下面来介绍一下 redis 的安装过程:
- 安装 gcc 编译
因为后面安装redis的时候需要编译,所以事先得先安装gcc编译。阿里云主机已经默认安装了 gcc,如果是自己安装的虚拟机,那么需要先安装一下 gcc:
yum install gcc-c++
- 下载 redis
有两种方式下载安装包,一种是去官网上下载(https://redis.io),然后将安装包考到 centos 中,另种方法是直接使用 wget 来下载:
wget http://download.redis.io/releases/redis-3.2.8.tar.gz
如果没有安装过 wget,可以通过如下命令安装:
yum install wget
- 解压安装
解压安装包:
tar –vzxf redis-3.2.8.tar.gz
然后将解压的文件夹 redis-3.2.8 放到 /usr/local/
下,一般安装软件都放在 /usr/local
下。然后进入 /usr/local/redis-3.2.8/
文件夹下,执行 make
命令即可完成安装。【注】如果 make 失败,可以尝试如下命令:
make MALLOC=libc
make install
- 修改配置文件
安装成功之后,需要修改一下配置文件,包括允许接入的 ip,允许后台执行,设置密码等等。打开 redis 配置文件:vi redis.conf
在命令模式下输入 /bind
来查找 bind 配置,按 n 来查找下一个,找到配置后,将 bind 配置成 0.0.0.0,允许任意服务器来访问 redis,即:
bind 0.0.0.0
使用同样的方法,将 daemonize 改成 yes (默认为 no),允许 redis 在后台执行。将 requirepass 注释打开,并设置密码为 123456(密码自己设置)。
- 启动 redis
在 redis-3.2.8 目录下,指定刚刚修改好的配置文件 redis.conf 来启动 redis:
redis-server ./redis.conf
再启动 redis 客户端:
redis-cli
由于我们设置了密码,在启动客户端之后,输入 auth 123456
即可登录进入客户端。然后我们来测试一下,往 redis 中插入一个数据:
set name CSDN
然后来获取 name
get name
如果正常获取到 CSDN,则说明没有问题。
3. Spring Boot 集成 Redis
3.1 依赖导入
Spring Boot 集成 redis 很方便,只需要导入一个 redis 的 starter 依赖即可。如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--阿里巴巴fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.35</version> </dependency>
3.2 Redis 配置
导入了依赖之后,我们在 application.yml 文件里配置 redis:
server port8080 spring #redis相关配置 redis database5 # 配置redis的主机地址,需要修改成自己的 host192.168.48.190 port6379 password123456 timeout5000 jedis pool # 连接池中的最大空闲连接,默认值也是8。 max-idle500 # 连接池中的最小空闲连接,默认值也是0。 min-idle50 # 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽) max-active1000 # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException max-wait2000
3.3 常用 api 介绍
Spring Boot 对 redis 的支持已经非常完善了,丰富的 api 已经足够我们日常的开发,这里我介绍几个最常用的供大家学习,其他 api 希望大家自己多学习,多研究。用到会去查即可。
有两个 redis 模板:RedisTemplate 和 StringRedisTemplate。我们不使用 RedisTemplate,RedisTemplate 提供给我们操作对象,操作对象的时候,我们通常是以 json 格式存储,但在存储的时候,会使用 Redis 默认的内部序列化器;导致我们存进里面的是乱码之类的东西。当然了,我们可以自己定义序列化,但是比较麻烦,所以使用 StringRedisTemplate 模板。StringRedisTemplate 主要给我们提供字符串操作,我们可以将实体类等转成 json 字符串即可,在取出来后,也可以转成相应的对象,这就是上面我导入了阿里 fastjson 的原因。
3.3.1 redis:string 类型
新建一个 RedisService,注入 StringRedisTemplate,使用 stringRedisTemplate.opsForValue()
可以获取 ValueOperations<String, String>
对象,通过该对象即可读写 redis 数据库了。如下:
public class RedisService { private StringRedisTemplate stringRedisTemplate; /** * set redis: string类型 * @param key key * @param value value */ public void setString(String key, String value){ ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue(); valueOperations.set(key, value); } /** * get redis: string类型 * @param key key * @return */ public String getString(String key){ return stringRedisTemplate.opsForValue().get(key); } 该对象操作的是 string,我们也可以存实体类,只需要将实体类转换成 json 字符串即可。下面来测试一下: SpringRunner.class) ( public class Course14ApplicationTests { private static final Logger logger = LoggerFactory.getLogger(Course14ApplicationTests.class); private RedisService redisService; public void contextLoads() { //测试redis的string类型 redisService.setString("weichat","程序员私房菜"); logger.info("我的微信公众号为:{}", redisService.getString("weichat")); // 如果是个实体,我们可以使用json工具转成json字符串, User user = new User("CSDN", "123456"); redisService.setString("userInfo", JSON.toJSONString(user)); logger.info("用户信息:{}", redisService.getString("userInfo")); } }
先启动 redis,然后运行这个测试用例,观察控制台打印的日志如下:
我的微信公众号为:程序员私房菜
用户信息:{"password":"123456","username":"CSDN"}
3.3.2 redis:hash 类型
hash 类型其实原理和 string 一样的,但是有两个 key,使用 stringRedisTemplate.opsForHash()
可以获取 HashOperations<String, Object, Object>
对象。比如我们要存储订单信息,所有订单信息都放在 order 下,针对不同用户的订单实体,可以通过用户的 id 来区分,这就相当于两个 key 了。
public class RedisService { private StringRedisTemplate stringRedisTemplate; /** * set redis: hash类型 * @param key key * @param filedKey filedkey * @param value value */ public void setHash(String key, String filedKey, String value){ HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash(); hashOperations.put(key,filedKey, value); } /** * get redis: hash类型 * @param key key * @param filedkey filedkey * @return */ public String getHash(String key, String filedkey){ return (String) stringRedisTemplate.opsForHash().get(key, filedkey); } } 可以看出,hash 和 string 没啥两样,只不过多了个参数,Spring Boot 中操作 redis 非常简单方便。来测试一下: public class Course14ApplicationTests { private static final Logger logger = LoggerFactory.getLogger(Course14ApplicationTests.class); private RedisService redisService; public void contextLoads() { //测试redis的hash类型 redisService.setHash("user", "name", JSON.toJSONString(user)); logger.info("用户姓名:{}", redisService.getHash("user","name")); } }
3.3.3 redis:list 类型
使用 stringRedisTemplate.opsForList()
可以获取 ListOperations<String, String> listOperations
redis 列表对象,该列表是个简单的字符串列表,可以支持从左侧添加,也可以支持从右侧添加,一个列表最多包含 2 ^ 32 -1 个元素。
public class RedisService { private StringRedisTemplate stringRedisTemplate; /** * set redis:list类型 * @param key key * @param value value * @return */ public long setList(String key, String value){ ListOperations<String, String> listOperations = stringRedisTemplate.opsForList(); return listOperations.leftPush(key, value); } /** * get redis:list类型 * @param key key * @param start start * @param end end * @return */ public List<String> getList(String key, long start, long end){ return stringRedisTemplate.opsForList().range(key, start, end); } }
可以看出,这些 api 都是一样的形式,方便记忆也方便使用。具体的 api 细节我就不展开了,大家可以自己看 api 文档。其实,这些 api 根据参数和返回值也能知道它们是做什么用的。来测试一下:
SpringRunner.class) ( public class Course14ApplicationTests { private static final Logger logger = LoggerFactory.getLogger(Course14ApplicationTests.class); private RedisService redisService; public void contextLoads() { //测试redis的list类型 redisService.setList("list", "football"); redisService.setList("list", "basketball"); List<String> valList = redisService.getList("list",0,-1); for(String value :valList){ logger.info("list中有:{}", value); } } }