一、Redis的概述
1.1 NoSQL的简介
1.1.1 NoSQL为什么会出现
从功能角度来讲,出现了各种编程语言
c语言,c++, java,scala,php,python等
从扩展角度来讲,对编程语言进行统一规范,设计各种接口,出现了各种编程语言的框架
structs,hibernate,mybatis,tomcat,RDBMS等
由于应用的请求数量越来越多,存储的数据越来越多,数据种类也越来越多,就出现了性能问题,为了解决性能问题
nginx,NoSql,MQ等
1.1.2 什么是NoSQL
1. NoSql, 是Not only Sql的简写,泛指非关系型数据库。
2. 为了解决高并发、高可扩展、高可用、大数据存储问题而产生的另一种数据库解决方案
3. 是RDBMS的良好补充,并不能取代RDBMS。(各有各的应用场景,RDBMS适合OLTP,Nosql适合OLAP)
4. NoSQL数据库基本上也都是基于内存的,所以访问速度也很快。
1.1.3 NoSQL的分类
#第一类:键值(Key-Value)存储数据库
相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型应用: 内容缓存,主要用于处理大量数据的高访问负载。
数据模型:一系列键值对
优势:快速查询
劣势:存储的数据缺少结构化
#第二类 列存储数据库
相关产品:Cassandra, HBase, Riak
典型应用:分布式的文件系统
数据模型:以列簇式存储,将同一列数据存在文件系统中
优势:查找速度快,可扩展性强,更容易进行分布式扩展
劣势:功能相对局限
#第三类:文档型数据库
相关产品:CouchDB、MongoDB
典型应用:Web应用(与Key-Value类似,Value是结构化的)
数据模型:一系列键值对
优势:数据结构要求不严格
劣势:查询性能不高,而且缺乏统一的查询语法
#第四类:图形(Graph)数据库
相关数据库:Neo4J、InfoGrid、Infinite Graph
典型应用:社交网络
数据模型:图结构
优势:利用图结构相关算法。
劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。
1.2 Redis的简介
1.2.1 Redis的介绍
1. redis是一个c语言开发的,开源的,基于内存的NoSql数据库。也可以用作消息缓存系统(对比kafka)
2. 提供了多种数据结构支持
strings:字符串
hashes:散列
lists:列表
sets:集合
sorted sets:带范围查询的有序集合,
bitmaps:位图类型
hyperloglogs: 超日志
geospatial:地理空间索引
streams:流
3. Redis内置了副本、Lua 脚本、LRU 驱逐、事务和不同级别的磁盘持久方式,
4. 可以通过Redis Sentinel和Redis Cluster的自动分区提供高可用性
5. 也可以对数据结构进行原子操作(说白了,就是对数据结构进行普通的CRUD)
1.2.2 Redis的应用场景
#1 缓存(数据查询、短连接、新闻内容、商品内容等等)。
这种应用场景的使用是最多的
#2 分布式集群架构中的session分离。
#3 聊天室的在线好友列表。
#4 任务队列。(秒杀、抢购、12306等等)
#5 应用排行榜。
#6 网站访问统计。
#7 数据过期处理(可以精确到毫秒)
1.2.3 Redis的特性
1. 访问速度快,原因是Redis基于内存存储
2. Redis也支持持久化操作,而且有两种方式,一种方式是dump到磁盘,一种方式是AOF
dump到磁盘: 就是存储内存中的具体数据
AOF: 除了存储具体数据外,还存储操作类型,比如是insert,delete,update等
3. Redis也支持集群模式,可以扩展多个服务节点
4. Redis相较于其他的缓存工具,支持的数据类型是非常丰富的。
二、Redis的安装部署
2.1 Redis的官网和下载
英文官网:https://redis.io/
中文官网:http://www.redis.cn/
下载:https://download.redis.io/releases/xxxxx.tar.gz
2.2 Redis的安装部署
2.2.1 注意事项:
1. 一般都是安装在linux系统上
2. 又因为c语言开发的,所以源码安装时,需要c语言环境
yum install gcc-c++
2.2.2 安装步骤
步驟1) 检查安装c语言环境
[root@qianfeng01 ~]# yum install gcc-c++
步骤2)上传、解压、更名
[root@qianfeng01 ~]# tar -zxvf redis-4.0.14.tar.gz -C /usr/local/
[root@qianfeng01 ~]# cd /usr/local/
[root@qianfeng01 local]# mv redis-4.0.14/ redis
步骤3)编译
[root@qianfeng01 local]# cd redis
[root@qianfeng01 redis]# make
步骤4)安装
[root@qianfeng01 redis]# make install PREFIX=/usr/local/redis
注意:此时在redis目录下,就会出现bin目录
步骤5)配置环境变量
[root@qianfeng01 redis]# vim /etc/profile
..........省略...........
#redis environment
export REDIS_HOME=/usr/local/redis
export PATH=$PATH:$REDIS_HOME/bin
[root@qianfeng01 redis]# source /etc/profile
#查看版本号
[root@qianfeng01 redis]# redis-cli --version
2.3 Redis服务的启动和关闭
2.3.1 启动方式
方式1)前台启动
只需要在命令行上输入redis-server脚本即可
[root@qianfeng01 redis]# redis-server
注意:由于是前台进程,如果ctrl+c了,就直接停止服务了。 所以不经常用
方式2)后台启动
#1: 将redis里的redis.conf拷贝到bin目录下
[root@qianfeng01 redis]# cp redis.conf bin/
#2: 修改bin下的redis.conf文件
[root@qianfeng01 bin]# vim redis.conf
...省略...
134 # By default Redis does not run as a daemon. Use 'yes' if you need it.
135 # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
136 daemonize yes <== 将no改为yes
#启动服务, 带上配置文件
[root@qianfeng01 bin]# redis-server /usr/local/redis/bin/redis.conf
查看进程
[root@qianfeng01 ~]# ps -ef | grep redis
root 31713 1 0 10:37 ? 00:00:00 redis-server 127.0.0.1:6379
root 31771 19391 0 10:38 pts/0 00:00:00 grep --color=auto redis
2.3.2 关闭方式
方式1)正规关闭方式
[root@qianfeng01 ~]# redis-cli -h <ip地址或者主机名> shutdown
方式2)kill掉
[root@qianfeng01 ~]# kill -9 pid
2.4 如何连接redis服务
2.4.1 命令行工具
[root@qianfeng01 ~]# redis-cli -h <主机ip或主机名> -p <端口号>
reg:
[root@qianfeng01 ~]# redis-cli -h qianfeng01 -p 6379
默认情况:
[root@qianfeng01 ~]# redis-cli
连接的是127.0.0.1
小贴士:
如果想要远程连接,需要将redis.conf里bind 127.0.0.1 修改为主机名 或者注释掉。
1. 如果修改为主机名,那么再连接时,一定要用到主机名,否则连不上
2. 如果是注释掉,可以本地连接,也可以远程连接。
2.4.2 Redis桌面管理工具
1. 双击安装即可
2. 配置参数:
Name: 连接名称,随便写
Host: 服务的ip或者host
Port: 端口号6379
Auth: 密码
注意:如果想要远程连接redis,需要修改redis.conf配置文件
方式1: 将69行对应的 bind 127.0.0.1 修改成主机名或者是ip
即:
bind qianfeng01
或者
bind 192.168.10.101
方式2: 注释掉即可
2.4.3 编程语言连接
1)说明
Redis不仅是使用命令来操作,也可以使用编程语言调用相关API接口进行连接。比如java、C、C#、C++、php、Node.js、Go等。
在官方网站里列一些Java的客户端api,有Jedis、Redisson、Jredis、JDBC-Redis等
官方推荐使用Jedis和Redisson。 在企业中用的最多的就是Jedis,下面我们就重点学习下Jedis。
Jedis同样也是托管在github上,地址:httpsRedis.assets//github.com/xetorthio/jedis
2)pom.xml
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0</version>
</dependency>
3)单线程连接方式
小贴士:需要将redis.conf里的protected-mode的no改为yes,即关闭保护模式。
package com.qf.redis.day01;
import redis.clients.jedis.Jedis;
/**
* 单线程连接redis
*/
public class RedisDemo01 {
public static void main(String[] args) {
/**
* Jedis(String host,int port)
*/
Jedis jedis = new Jedis("qianfeng01", 6379);
//调用ping指令 向远程主机发送信息,验证网络通信是否正常,返回pong 表示畅通
String ping = jedis.ping();
System.out.println(ping);
//设置字符串类型的一个键值对,
String setAck = jedis.set("girlfriend", "gaoyuanyuan");
System.out.println(setAck);
//从redis中获取girlfriend对应的value值
String getAck = jedis.get("girlfriend");
System.out.println(getAck);
jedis.close();
}
}
4)线程池连接方式
package com.qf.redis.day01;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* 使用线程池连接redis
*/
public class RedisDemo02 {
public static void main(String[] args) {
/**
* 创建一个线程池对象
* 构造器:
* JedisPool(String host,int port)
* JedisPool(GenericObjectPoolConfig config,String host)
*/
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(20); //设置线程池中的最大值
config.setMaxIdle(7); //设置线程池中的最大空闲连接数
config.setMinIdle(5); //设置线程池中的最小空闲连接数
config.setMaxWaitMillis(5000); //设置超时时间,单位毫秒
JedisPool pool = new JedisPool(config, "qianfeng01");
//从池子中获取一个具体的连接对象
Jedis jedis = pool.getResource();
//设置键值对
String set = jedis.set("hobby", "movie");
System.out.println(set);
//获取key对应的value
String hobby = jedis.get("hobby");
System.out.println(hobby);
jedis.close();// 将连接归还到连接池中
}
}
2.5 Redis的密码策略
进入redis.conf文件,找到500行左右,解开注释,设置密码,修改后别忘记重启服务
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
requirepass 123123 <== 解开注释,设置密码
# Command renaming.
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG com
连接:需要使用-a 来设定密码
[root@qianfeng01 bin]# redis-cli -h qianfeng01 -p 6379 -a 123123
程序中如下设置:
jedis.auth("123123");
2.6 redis的常规操作
2.6.1 库操作
1. redis的默认的db的个数是16个。id从0到15
2. 切换数据库
select dbid
3. 清空当前数据库(慎用)
flushdb
4. 清空所有的数据库(慎用)
flushall
2.6.2 Redis的键
1. #根据匹配模式查询相关的key
keys * #查询所有的key
keys ?O* #查询第二个字符是O的key
2. dbsize #查看当前库下所有的key的个数
3. exists key #判断某一个key是否存在, 0表示不存在,1表示存在
4. type key #查看key的类型
5. del key #删除某一个key 1 表示删除成功 0表示删除失败
6. unlink key #删除某一个key(非阻塞删除)
#仅将key从keyspace元数据中删除,真正的删除会在后续中异步删除 (先奏后斩的意思)
7. expire key seconds #设置key的存活时间
8. persist key #清除key的存活时间, 已经过期的清除没有意义
9. ttl key #查看key的存活时间 -2表示过期 -1 表示永不过期
小故事
6379这个端口号,来源于一个意大利歌女的名字 merz
三、Redis的类型
Redis在存储数据时,都是以键值对的形式存储的,这个key的作用是用于指向value的,可以通过这个key获取具体的value值。我们所说的丰富的数据类型是针对于value来说的。key只是用来做映射关系。
那么key的长度是越长越好?还是越短越好?
都不是,尽量做到见名知意。
比如存储身份证是xxxxx1901xxxx的张三的这个人的爱好
set xxxxx1901xxxx-zhangsan-hobbys book movie eat
太长占内存
太短的话:做不到见名知意
3.1 Redis的五大常用类型
3.1.1 字符串类型
3.1.1.1 介绍
这是redis中的最简单类型。如果你只用这种类型,Redis就像一个可以持久化的memcached服务器(注:memcache的数据仅保存在内存中,服务器重启后,数据将丢失)。
由于 Redis 的键是字符串,所以当我们也使用字符串类型作为值时,我们是在将一个字符串映射到另一个字符串。字符串数据类型可用于许多用例,例如缓存 HTML 片段或页面。
应用场景: 可以将内存中的对象,进行存储到redis中
3.1.1.2 命令行常用指令
set指令的语法格式:set key value [EX seconds] [PX milliseconds] [NX|XX]
EX: KV的存活时间,单位是秒
PX: KV的存活时间,单位是毫秒
NX: K不存在时,会设置成功
XX: K已经存在时,会覆盖
get指令的语法格式:
get key
qianfeng01:6379[1]> set city changchun EX 100 NX
OK
qianfeng01:6379[1]> keys *
1) "city"
2) "word"
qianfeng01:6379[1]> set city beijing EX 100 NX <== 会失败,因为city已经存在
(nil)
qianfeng01:6379[1]> get city
"changchun"
qianfeng01:6379[1]> set city beijing XX <== 会成功,因为city已经存在
OK
qianfeng01:6379[1]> get city
"beijing"
qianfeng01:6379[1]>
qianfeng01:6379[1]> append city shanghai <== 在key对应的原有的value上追加字符串
(integer) 15
qianfeng01:6379[1]> get city
"beijingshanghai"
qianfeng01:6379[1]> set num 1
OK
qianfeng01:6379[1]> decr num <== 递减1 要求 value的类型是整形
(integer) 0
qianfeng01:6379[1]> DECRBY num 5 <== 递减5 指定步长
(integer) -5
qianfeng01:6379[1]> get city
"beijingshanghai"
qianfeng01:6379[1]> GETRANGE city 0 2 <== 获取指定坐标之间的字符串,是一个闭区间
"bei"
qianfeng01:6379[1]> GETSET city shenyang <== 覆盖值,并返回原有的值
"beijingshanghai"
qianfeng01:6379[1]> get num
"-5"
qianfeng01:6379[1]> incr num <== 自增+1
(integer) -4
qianfeng01:6379[1]> INCRBY num 2 <== 指定自增的步长
(integer) -2
qianfeng01:6379[1]> mset username zhangsan age 23 gender f isMarry false <== 设置多对KV
OK
qianfeng01:6379[1]> mget username age gender isMarry num <== 获取多个Key的value值
1) "zhangsan"
2) "23"
3) "f"
4) "false"
5) "-2"
3.1.1.3 代码演示
package com.qf.redis.day01;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
import java.util.List;
/**
* 练习Redis的字符串类型的API
*/
public class RedisDemo03_String {
public static void main(String[] args) {
getOfString();
}
//set命令的测试
public static void setOfString(){
Jedis jedis = new Jedis("qianfeng01", 6379);
jedis.auth("123123");
jedis.set("classno","sz2103");
SetParams setParams = new SetParams();
setParams.ex(100); //设置存活时间,单位是秒
//setParams.px(50000); //设置存活时间,单位是毫秒
jedis.set("teacher","michael",setParams);
jedis.setnx("teacher1","anjinglaoshi");
jedis.append("city"," is good");
jedis.incr(