关于redis学习专栏的第一篇文章介绍redis基础初识,主要介绍什么是redis、redis特性、redis的安装启动和连接以及Redis在Java客户端中使用等基础知识
目录
前言
施主,既然来了,就静下心来,仔细阅读好好思考!
老衲才疏学浅,如有错误,还请各位大侠在评论区不吝赐教。
正文
一、什么是Redis
百度百科专业解释:Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
二、Redis的特性
redis的特性非常多,我们先罗列出来然后一项一项介绍:速度快、支持持久化、支持多种数据结构、支持多种客户端语言、功能丰富、使用简单、支持主从复制、支持高可用和分布式。
- 速度快:主要因为数据是存在在内存当中,客户端通过redis操作数据都是基于内存的操作;
- 支持持久化:内存是有丢失数据的风险,磁盘才能永久保存数据,所以Redis提供RDB和AOF两种方式进行数据的持久化操作(后面会详细介绍两种持久化方式);
- 支持多种数据结构:支持的数据结构分别有String字符串、Hash表、List链表、Set集合、SortSet有序集合(相关博客:Redis常用数据类型以及底层数据结构分析),另外还有几个高级的数据结构BitMaps位图、HyperLogLog、GEO地理信息定位,后续文章会详细介绍;
- 支持多种客户端语言:链接Redis的客户端可以是Java、PHP、Python等多种语言的客户端,我们会详细介绍Java的客户端使用;
- 功能丰富:支持发布订阅、pipeline、事务还有Lua脚本,后面会详细介绍到前两者;
- 使用简单:redis开发代码非常少、不依赖外部库、单线程模型,对redis操作也简单;
- 支持主从复制:可以通过主从结构分散对redis的访问压力,提高高性能;
- 支持高可用和分布式:通过redis-sentinel实现redis的高可用、通过redis-cluster支持分布式,后面文章会详细介绍。
三、Redis应用场景
redis的使用场景没有特定的一个规定,在实际的工作动作,可以结合redis的功能特性和实际的需求使用,不局限于某些经典的使用场景,redis在业界典型的应用场景有(不局限于以下统计):
- 缓存系统:为了减少外部高并发的请求对系统和数据库造成压力,通过将数据库的热点数据以及临时的操作数据(这里还是要根据使用redis的具体情况来定)用redis进行缓存,这样可以提高系统的处理速度和提供系统的性能。
- 计数器: 比如像博客微博的点赞和评论数,就可以用轻量级的redis进行统计。
- 消息队列系统:消息队列可以用当前各种成熟的MQ消息列实现,但是也可以通过redis来实现消息队列的功能。
- 排行榜:比如可以根据redis提供的有序集合这样的数据结构,实现一个排行榜功能。
- 社交网络:根据redis的数据结构,可以用在比如现在很多社交媒体如抖音微博用户的粉丝关注、用户动态等数据都可以用redis来实现。
四、Redis的安装、启动和链接
1. redis的安装
Linux环境下的安装步骤,可以自行选择不同的redis的版本,下面只是示例:
// 下载压缩包
wget http://download.redis.io/releases/redis-3.0.7.tar.gz
// 解压
tar -xzf redis-3.0.7.tar.gz
// 进入到下载的目录
cd redis
// 进行编译安装
make && make installredis在windows网上有很多文章,大家可以自行查阅,很简单,给个博客地址给大家:https://www.cnblogs.com/jylee/p/9844965.html。下面根据上面的安装命令进行安装之后,咱们进行启动
2. redis的三种启动方法
(1)简单启动:执行命令redis-server,端口和配置都是用的默认的;
(2)动态参数启动:执行命令redis-server -port 6390,使用动态参数启动,指定启动后的端口为6390;
(3)配置启动:执行命令redis-server configPath(配置文件路径),通过将所有配置属性写在配置文件中启动。
如果要用到自定义配置,先了解一下常用的配置项,后续文章也会介绍涉及到的一些高级的配置项(可以进到安装的redis目录查看redis.config文件,这里面是默认的配置项):
- daeonize:是否守护进程启动(yes|no);
- port:启动的端口(多机情况下肯定需要配置);
- logfile:redis工作时打印的日志文件名称;
- dir:redis的工作目录,定义了该值之后redis的日志文件和持久化文件就会保存在这个目录下面。
启动并且链接上某个redis服务之后可以通过命令查看当前服务的一个配置:config get *
daemonize 设置yes或者no区别:
- daemonize-yes:redis采用的是单进程多线程的模式。当redis.conf中选项daemonize设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。
- daemonize-no:当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。
启动之后,可以重新打开一个链接窗口,进行后续的redis命令来操作redis啦。
验证是否成功启动可以通过 :
ps -ef | grep redis查看redis的进程状态

netstat -antpl | grep redis查看redis的端口(默认6379)是否是监听状态

redis -cli -h ip -p port ping通过ping来查看
![]()
(我这里用的是远程的服务器,ip的值直接用localhost比较快,我用ip的话好慢)
最后说下关闭redis服务:
redis-cli -p 端口号 shutdown3. redis的客户端链接
如果redis在本机并且是默认端口的话直接执行redis-cli就可以链接了
![]()
如果redis的服务在远程的话就表明端口执行命令:redis-cli -h ip地址 -p port端口号
redis数据类型相关的讲解就不在这篇文章介绍了,我的博客:Redis常用数据类型以及底层数据结构分析,有详细的介绍,大家可以去阅读。
五、Redis在Java客户端的使用
(1)Jedis简单的直连示例
redis在java客户端中使用是通过Jedis,Jedis就是基于Java语言开发的redis客户端。其实我们上面使用的redis-cli也是redis的一种客户端,通过redis-cli链接redis后可以执行相关的redis命令比如set key value,Jedis链接之后也是一样的模式,只是是java对象,比如设置一个string类型的数据jedis.set("key", "value")。
首先在spring项目中的pom中引入redis依赖:

然后进行简单的使用,前提是确保redis服务器是启动,否则jedis是链接不上的,可以看使用还是非常简单的
public class RedisClient {
public static void main(String[] args) {
// 1.生成jedis客户端
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 2.执行相关命令操作:简单设置一个string字符串数据
jedis.set("jedis", "hello");
System.out.println(jedis.set("str1", "value1")); // 输出OK
System.out.println(jedis.get("jedis")); // 输出hello
jedis.close();
}
}其他的数据类型的命令jedis类中都有封装,具体可以查看方法列表并且实操一下:

(二)Jedis的连接池使用
上面我们是通过简单粗暴的直连方式进行对redis操作,步骤是:生成Jedis实例对象,此时底层是通过TCP进行链接redis服务器端 -> 然后通过jedis执行命令 -> 然后redis服务器返回执行命令的结果 -> 最后关闭jedis的链接,通过下图理解:

这种粗暴的直连方式意味着每次使用都要进行重复的TCP链接然后关闭链接操作,那在频繁操作redis的业务场景下,这种方式是非常影响系统的性能并且给服务带来非常大的压力,一方面就是进行频繁的TCP链接时的三次握手关闭链接时的时候四次挥手,其次就是频繁创建的对象会增加GC的次数,大家是不是想到这种场景和创建线程相似?是的,为了优化性能就提出了线程池的机制,在Jedis中其实也是存在这种优化机制,那就是我们接下来要讲的Jedis连接池, 步骤是:首先从jedis线程池中拿jedis实例对象 -> 然后通过jedis执行命令 -> 然后redis服务器返回执行命令的结果 -> 最后使用完将jedis对象返还给连接池,这样就避免频繁的进行TCP链接、TCP断开链接以及对象的创建和销毁相关操作,通过下图理解:

现在我们来看下代码实现,我们知道像线程池这种肯定是要用单例模式的,同样我们使用Jedis连接池也肯定要用单利模式,不然就需要频繁的创建连接池了,那比频繁创建Jedis实例更加消耗性能,我们来看下代码:
首选在服务端创建一个单例的线程池:
public class JedisPoolTool { // 线程安全的单例模式
private volatile static JedisPool jedisPool= null;
private JedisPoolTool(){}; // 既然是单例模式,构造方法就不允许别人调用
public static JedisPool getJedisPoolTool(){
if (jedisPool == null){
synchronized (JedisPoolTool.class){
if (jedisPool == null){
jedisPool = buildJedisPool();
}
}
}
return jedisPool;
}
private static JedisPool buildJedisPool(){
// 自定义指定连接池的对象数
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10); // 设置最大连接数
jedisPoolConfig.setMaxIdle(8); // 设置最大空闲连接数
jedisPoolConfig.setMinIdle(2); // 设置最小空闲连接数
// 构造JedisPool实例并返回,我用的是本机的参数
return new JedisPool(jedisPoolConfig, "127.0.0.1", 6379);
}
}这里我们用Jedis提供的JedisPoolConfig来自定义连接池配置,如果不传这个参数的话Jedis会使用默认的配置,有兴趣的同学可以详细看下源码,文章后面也会介绍,现在我们先看客户端的使用:
public class RedisPoolClient {
public static void main(String[] args) {
// 1.从线程池中获取jedis链接对象
Jedis jedis = JedisPoolTool.getJedisPoolTool().getResource();
// 2.执行相关命令操作:简单设置一个string字符串数据
System.out.println( jedis.set("jedisPool", "jedisPoolHello")); // 输出OK
System.out.println(jedis.get("jedisPool")); // 输出jedisPoolHello
jedis.close(); // 归还jedis资源到连接池
}
}注意:jedis直连和使用jedis连接池的客户端中,最后都是进行了jedis.close()函数,该函数如果jedis是通过直连的方式那就会进行jedis链接关闭,如果jedis是来之连接池的话就会归还给连接池,看下源码:
public void close() {
if(this.dataSource != null) { // 来之连接池的关闭方式
if(this.client.isBroken()) {
this.dataSource.returnBrokenResource(this);
} else {
this.dataSource.returnResource(this);
}
} else {
this.client.close(); // 直连走的关闭方式,关闭jedis的连接
}
}(三)Jedis连接池配置介绍
我们来看看连接池的几个常见的配置项,(相关的默认值大家可以阅读源码,非常直观):
- maxTotal:连接池中最大连接数;
- maxIdle:连接池中最大空闲连接数;
- minIdle:连接池中最小空闲连接数;
- jmxEnabled:是否开启jmx监控,默认是true(这个没有实操过);
- blockWhenExhausted:当连接池没有空闲连接时,调用者在获取连接对象时是否等待,建议使用;
- maxWaitMillis:最大等待时间(单位毫秒),和上面的blockWhenExhausted为true的时候结合使用,默认是永远不超时,不建议默认;
- testOnBorrow:当从连接池借用连接时,是否对所获取的连接做有效性检测(Ping),无效连接会被移除,建议默认false;
- testOnReturn:当向连接池还连接时是否做有效性检测,无效连接会被移除,建议默认false。
现在我们来看下应该怎么去考虑一个合适的maxTotal值:如果命令平均执行时间为0.1ms -> 0.001s,业务需要的QPS是50000,那maxTotal理论值应该可以为0.001 * 50000 = 50个,但实际值要偏大一些。也就是我们从两个维度来考虑:业务并发量和客户端执行命令时间,但是前提是maxTotal的值肯定要小于redis配置的最大连接数,可以通过命令config get maxclients来查看具体的值:

六、总结
本篇文章从介绍redis是什么,到redis的八个特性分析,再到redis的适用场景的介绍,后续讲述了redis在Linux环境的安装流程、三种启动方法以及客户端的链接redis-cli,然后就是在Java中使用redis的Jedis客户端的使用方法,在jedis小节我们主要学习jedis直连和连接池两种方式来获取对redis的链接,最后简单介绍了连接池的几个常用的配置,最后感谢大家阅读!