- Redis概念
- Redis的安装
- Redis命令入门
- Java操作Redis
- Redis的持久化配置
- Redis的淘汰策略
一.Redis概念
1.NOSQL
1.1.什么是NOSQL
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,它泛指非关系型的数据库。
关系型数据库:以关系(由行和列组成的二维表)模型建模的数据库。简单理解:有表的就是关系型数据库。
1.2.NOSQL分类
http://www.nosql-database.org/
分类 | Examples举例 | 典型应用场景 | 数据模型 | 优点 | 缺点 |
---|---|---|---|---|---|
键值(key-value) | Tokyo Cabinet/Tyrant, Redis , Memcached , Voldemort, Oracle BDB | 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。 | Key 指向 Value 的键值对,通常用hash table来实现 | 查找速度快 | 数据无结构化,通常只被当作字符串或者二进制数据 |
列存储数据库 | Cassandra, HBase, Riak | 分布式的文件系统 | 以列簇式存储,将同一列数据存在一起 | 查找速度快,可扩展性强,更容易进行分布式扩展 | 功能相对局限 |
文档型数据库 | CouchDB, MongoDb | Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) | Key-Value对应的键值对,Value为结构化数据 | 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 | 查询性能不高,而且缺乏统一的查询语法。 |
图形(Graph)数据库 | Neo4J, InfoGrid, Infinite Graph | 社交网络,推荐系统等。专注于构建关系图谱 | 图结构 | 利用图结构相关算法。比如最短路径寻址,N度关系查找等 | 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群 |
Redis和Memcached是key-value的noSql,主要用来做缓存。
2.Redis
2.1.什么是Redis
Redis 是一个高性能的 开源的、C语言写的Nosql(非关系型数据库),redis的数据可以存储在内存中或者磁盘中。Redis 是以key-value形式存储,和传统的关系型数据库不一样。不一定遵循传统数据库的一些基本要求,比如说,不遵循sql标准,事务,表结构等等,redis严格上不是一种数据库,应该是一种数据结构化存储方法的集合。
数据结构:数组、List Set Map等
Redis是将数据保存到内存的nosql。它有很多的方法,使用特定的方法就可以将存入的字符串转化为特定的数据结构保存。
2.2.Redis的特点
- 数据保存在内存,存取速度快,并发能力强
- 它支持存储的value类型相对更多,包括string(字符串)、list(链表-有序可重复集合)、set(无序不可重复集合)、 zset(sorted set --有序不可重复集合)和hash(哈希类型-对象)。
- redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库(如MySQL)起到很好的补充作用。
- 提供了Java,C/C++,C#,PHP,JavaScript等客户端,使用很方便。
- Redis支持集群(主从同步)。数据可以主服务器向任意数量从的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。
- 支持持久化,
- 支持订阅/发布
总结:
1、redis是C语言写的开源免费的NoSql数据库
2、数据存放在内存,还支持持久化。存取数据快,并发能力强,数据安全高。
3、value支持的数据类型多。
4、支持多个语言客户端。
5、支持集群。(支持高并发,海量数据)
2.3.Redis、Memcached、Mysql的比较
mysql | redis | memcached | |
---|---|---|---|
类型 | 关系型 | 非关系型 | 非关系型 |
存储位置 | 磁盘 | 磁盘和内存 | 内存 |
存储过期 | 不支持 | 支持 | 支持 |
读写性能 | 低 | 非常高 | 非常高 |
存储过期:一个数据存储时为他设置过期时间,时间一到数据就没有. 道具,会员,优惠券,订单,红包等
2.4.Redis的使用场景
-
缓存经常查询数据,放到读速度很快的空间(内存),以便下次访问减少时间。减轻数据库压力,减少访问时间.而redis就是存放在内存中的。就如同:Mybatis 二级缓存 , ehcache框架 缓存。
-
计数器网站通常需要统计注册用户数,网站总浏览次数等等 ,新浪微博转发数、点赞数。
-
实时防攻击系统防止暴力破解,如使用工具不间断尝试各种密码进行登录。解决方案使用Redis记录某ip一秒访问到达10次以后自动锁定IP,30分钟后解锁
-
设定有效期的应用设定一个数据,到一定的时间失效。验证码,登录过期, 自动解锁,购物券,红包。
-
自动去重应用Uniq 操作,获取某段时间所有数据排重值 这个使用 Redis 的 set 数据结构最合适了,只需要不断地将数据往 set 中扔就行了,set 意为 集合,所以会自动排重。
-
排行榜 可以利用redis的zset来进行处理
-
队列构建队列系统 使用 list 可以构建队列系统,使用 sorted set 甚至可以构建有优先级的队列系统。 秒杀:可以把名额放到内存队列(redis),内存就能处理高并发访问。
-
消息订阅系统:Pub/Sub 构建实时消息系统 Redis 的 Pub/Sub 系统可以构建实时的消息系统,比如很多用 Pub/Sub 构建的实时聊天系统 的例子。如QQ群
二.Redis的安装
1.下载和安装
1.1.下载Redis
-
linux版本:http://redis.io/download
-
中文网地址:https://www.redis.net.cn/
-
windows版本: https://github.com/microsoftarchive/redis/releases
1.2.安装Redis
-
window版本解压Redis包即可
-
linux版本安装暂时不讲,后面会讲到,有兴趣可以自己百度
1.3.Redis目录介绍
redis.window.conf # reids配置文件
redis-benchmark.exe #reids性能测试工具
redis-check-aof.exe #aof文件校验、修复功能
redis-check-dump.exe #rdb文件校验、修复功能
redis-cli.exe # 命令行客户端,连接Redis服务端可对Redis进行相关操作
redis-server.exe # Redis服务器,启动Redis
2.Redis启动和测试
2.1.启动redis-server
进入到Redis安装目录 ,虽然双击也可以启动,但是建议使用CMD执行
redis-server.exe redis.windows.conf
2.2.启动redis-client
-
连接本机Redis直接双击 redis-cli.exe 或者执行命令
redis-cli.exe
-
如果连接其他服务的Redis需要跟上 -h参数
redis-cli.exe -h ip -p 端口 #如 redis-client.exe -h 192.168.0.11 -p 6379
2.3 测试Redis
set name zs #设置数据
get name #获取数字
expire name 30 # 设置过期时间
ttl name #获取过期时间
keys * # 获取所有的key
2.4 设置密码
2.4.1 临时设置
-
CONFIG SET 命令可以动态地调整 Redis 服务器的配置而无须重启,重启后失效
config set requirepass 123456
2.4.2 永久设置
-
修改配置文件 redis.widows.conf ,增加代码:
requirepass 123456
2.4.3 登录
auth 123456
三.Redis命令入门
1.String的操作
2.1.String结构
- String结构模拟图
key | value |
---|---|
name | zs |
age | 18 |
2.2.set key value
-
将单个字符串值value关联到key,存储到Redis
set name zs #key为 name, 值为zs
2.3.get key
-
返回key关联的字符串值
get name #获取值,key为 name
2.4.mset key value key value
-
同时设置一个或多个 key-value 对
mset name zs age 18 #设置了两对key ,name=zs ; age=18
2.5.mget key key
-
获取多个值
mget name age #获取key为name和age的数据的值
2.6.incr key
-
将 key 中储存的数字值增1(key不存在,则初始化为0,再加1)
incr age #age的值增加1
2.7.decr key
-
将 key 中储存的数字值减1(key不存在,则初始化为0,再减1)
decr age #将age的值减去1
2.8.incrby key number
-
将 key 中储存的数字值增加指定数字
incrby age 2 #在age的值的基础上增加2
2.9.decrby key number
-
将 key 中储存的数字值减少指定数字
decrby age 2 #在age的值的基础上减去2
2.10.SETEX key seconds value
-
设置key-value,并设置过期时间
setex mykey 10 “Hello” #设置 mykey的值为“hello” ,过期时间为 10s ,是set和expire的组合命令,且是原子性的
2.11.SETNX key value
-
设置一个key-value,如果这个key不存在则设置成功返回1,否则设置不成功,返回0
setnx name zs
2.12.GETSET key value
-
设置一个key-value,把这个key以前的值返回
getset name ls
2.key的操作
2.1.keys
-
查看所有的key
keys *
2.2.del key
-
删除指定的某个key
del username #删除key为username的数据
2.3.expire key secnods
-
设置key的过期时间(secnods秒后过期)
expire name 10 #设置name的过期时间10s
2.4.ttl key
-
查看key的过期时间
ttl name #查看name的过期时间
2.5.flushall
-
清空整个redis服务器数据,所有的数据库全部清空
flushall
2.6.flushdb
-
清除当前库
flushdb
2.7.select index
-
选择数据库,redis中默认有16个数据库,名称分别为0,1,2,15 , index数据库索引
select 1 #选择第2个数据库
2.8.exists key
-
查询key是否存在
exists name
3.List的操作
3.1.List结构
list集合可以看成是一个左右排列的队列(列表)
-
List机构模拟图
key value value value names zs ls ls ages 11 18 20
3.2.lpush key value value
-
将一个或多个值 value 插入到列表 key 的表头(最左边)
lpush names zs ls #往key为 names 的list左边添加值“zs”和“ls”
3.3.lrange key start stop
-
返回列表 key 中指定区间内的元素,查询所有的stop为-1即可
lrange names 0 -1 #查看names的所有元素
3.4.rpush key value value
-
将一个或多个值 value 插入到列表 key 的表尾(最右边)
rpush names zl cq #往key为 names 的list右边添加值“zl”和“cq”
3.5.lpop key
-
移除并返回列表 key 的头(最左边)元素。
lpop names #移除并返回names列表的头(最左边)元素
3.6.rpop key
-
移除并返回列表 key 的尾(最右边)元素。
rpop names #移除并返回names列表的尾(最右边)元素。
3.7.lrem key count value
-
根据count值移除列表key中与参数 value 相等的元素count >0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。count = 0 : 移除表中所有与 value 相等的值。
lrem names 1 zs #删除names列表中左边第1个“zs”
lrem names 0 ls #删除names列表中所有的“ls”
lrem names -1 cq #删除names列表中右边第1个“cq”
3.8.lindex key index
-
返回列表 key 中,下标为 index 的元素
lindex names 2 #取names列表中索引为 2 的元素
3.9.ltrim key start stop
-
对一个列表进行修剪 ,保留范围内的,范围外的删除
ltrim names 2 4 #删除names列表中索引为 2 - 4 以外的元素
3.10.Redis中如何实现栈和队列
- list控制同一边进,同一边出就是栈
- list控制一边进,另一边出就是队列
4.Set的操作
set集合是一个无序的不含重复值的队列
4.1.Set结构
- Set机构模拟图
key | value | value | value |
---|---|---|---|
idcards | 110 | 120 | 130 |
phones | 182 | 135 | 136 |
4.2.sadd key value value
-
将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略
sadd colors red green yellow blue #往colors这个set集合中存放元素: red,green,yellow,blue
4.3.smembers key
-
返回集合 key 中的所有成员。
smembers colors
4.4.srem key member
-
移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略
srem colors red #删除colors中的 red元素
4.5.SCARD key
-
返回集合存储的key的基数 (集合元素的数量).如果key不存在,则返回 0。
scard colors
4.6.SDIFF key [key …]
-
返回一个集合与给定集合的差集的元素
sdiff colors names
4.7.SISMEMBER key member
-
返回成员 member 是否是存储的集合 key的成员.
-
如果member元素是集合key的成员,则返回1
-
如果member元素不是key的成员,或者集合key不存在,则返回0
sismember names zs #判断names中是否包含 zs
5.ZSet的操作
ZSet(sorted sets)在Set基础上增加了“分数”,让set集合有了排序功能
5.1.ZSet结构
- ZSet结构模拟图
key | value(score) | value(score) | value(score) |
---|---|---|---|
names | zs(10) | ls(20) | ww(30) |
5.2.zadd key score value score value
-
将所有指定成员添加到键为
key
有序集合(sorted set)里面,如果指定添加的成员已经是有序集合里面的成员,则会更新改成员的分数(scrore)并更新到正确的排序位置zadd heights 150 zs 160 ls #有序集合heights中zs的分数为150 ,ls的分数是 160
5.3.ZCARD key
-
返回key的有序集元素个数。key存在的时候,返回有序集的元素个数,否则返回0。
zcard heights
5.4.ZCOUNT key min max
-
返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员。
zcount heights 150 160 #获取heignhts中分数为 150到160的元素数量
5.5.ZPOPMAX key [count]
-
删除并返回有序集合
key
中的最多count
个具有最高得分的成员。如未指定,count
的默认值为1。zpopmax heights 2 #删除最高分数的前2个元素
5.6.ZPOPMIN key [count]
-
删除并返回有序集合
key
中的最多count
个具有最低得分的成员。如未指定,count
的默认值为1。zpopmin heights 2 #删除最低分数的前2个元素
5.7.ZRANGE key start stop [WITHSCORES]
-
返回存储在有序集合
key
中的指定范围的元素。 返回的元素可以认为是按得分从最低到最高排列。 如果得分相同,将按字典排序。返回给定范围内的元素列表(如果指定了WITHSCORES
选项,将同时返回它们的得分)。zrange heights 0 10 WITHSCORES #返回heights中索引 0 到 10 的元素和其分数
5.8.ZRANK key member
-
返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。排名以0为底,也就是说,score值最小的成员排名为0。
zrank heights zs #返回 zs在heights的分数从小到大排名
5.9.ZREVRANK key member
-
返回有序集key中成员member的排名,其中有序集成员按score值从大到小排列。排名以0为底,也就是说,score值最大的成员排名为0。
zreverank heights zs #返回 zs在heights的分数从大到小排名
5.10.ZSCORE key member
-
返回有序集key中,成员member的score值。如果member元素不是有序集key的成员,或key不存在,返回nil。
zscore heights zs #返回 zs的分数
5.11.ZREVRANGE key start stop [WITHSCORES]
-
返回有序集key中,指定区间内的成员。其中成员的位置按score值递减(从大到小)来排列。具有相同score值的成员按字典序的反序排列。
ZREVRANGE heights 1 2 WITHSCORES #返回索引1 - 2 的成员,按分数大到小排序
5.12.ZRANGEBYSCORE key min max WITHSCORES LIMIT offset count
-
返回有序集合中指定分数区间内的成员,分数由低到高排序,LIMIT控制分页
ZRANGEBYSCOREkey heights 0 170 WITHSCORES LIMIT 0 10 #查询heights中0-170分之间的元素,低到高排序,0条 #开始查询,每页10条
5.13.ZREVRANGEBYSCORE key max min WITHSCORES LIMIT offset count
- 返回有序集合中指定分数区间内的成员,分数由高到低排序,LIMIT控制分页
指令 | 是否必须 | 说明 |
---|---|---|
ZREVRANGEBYSCORE | 是 | 指令 |
key | 是 | 有序集合键名称 |
max | 是 | 最大分数值,可使用"+inf"代替 |
min | 是 | 最小分数值,可使用"-inf"代替 |
WITHSCORES | 否 | 将成员分数一并返回 |
LIMIT | 否 | 返回结果是否分页,指令中包含LIMIT后offset、count必须输入 |
offset | 否 | 返回结果起始位置 |
count | 否 | 返回结果数量 |
ZREVRANGEBYSCORE heights 170 0 WITHSCORES LIMIT 0 10 #返回heights中分数为170-0之间从第0条数查,10条
6.Hash的操作
Hash类似于jdk中的Map,一个key下面以键值对的方式存储数据
6.1.Hash结构
- Hash机构模拟图
6.2.HSET key field value
-
设置 key 指定的哈希集中指定字段的值。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。如果字段在哈希集中存在,它将被重写。
hset user:1 name zs #给"user:1"这个key设置name=zs键值对
6.3.HGet key name
-
获取hash类型的name键对应的值
hget user:1 name #获取user:1总的name字段
6.4.HMSET key field value field value
-
批量添加name=value键值对到key这个hash类型
hmset user:2 name zs age 18 #给"user:2"这个key设置name=zs键值对和age=18键值对
6.5.HMGET key field field
-
批量获取hash类型的键对应的值
hmget user:2 name age #获取user:2总的name和age字段
6.6.hkeys key
-
返回哈希表 key 中的所有键
hkeys user:2 #返回user:2总的所有字段
6.7.hvals key
-
返回哈希表 key 中的所有值
hvals user:2 #返回user:2中的所有值
6.8.hgetall key
-
返回哈希表 key 中,所有的键和值
hgetall user:2 #返回user:2中所有key和value
6.9.存储对象的两种方式
-
使用string结构
set user:1 {id:1,name:zs}
-
使用hash
hset user:2 {id:2,name:ls}
7.其他
7.1.SORT key
-
对 list ,set ,zset进行排序
SORT ages #对年龄集合进行排序
SORT ages DESC #对年龄集合进行排序,倒排
SORT names ALPHA #对姓名集合进行字典顺序排序
SORT names LIMIT 0 10 # 取names集合中,从第 0 个元素,往后取10个元素
SORT names LIMIT 0 5 ALPHA DESC # 取集合中前5个元素,按字典顺序倒排
四.Java操作Redis
1.Java集成Jedis
开始在 Java 中使用 Redis 前, 我们需要确保已经安装并启动 redis 服务及 Java redis 驱动,且你的机器上能正常使用 Java。可以取Maven仓库下载驱动包 下载 jedis.jar,。
1.1.搭建工程
- 搭建普通java项目,项目名:jedis-demo
1.2.导入Jedis依赖
-
把Jedis和连接池包一起导入进来
commons-pool2-2.2.jar #连接池
jedis-2.5.2.jar #Jedis核心包
2.3.编写测试类
- 通过Jedis客户端对象连接Redis,调用API进行Redis
@Test
public void testJedis()throws Exception{
//创建连接
String host ="127.0.0.1";
//端口
int port = 6379;
//超时时间,1秒超时
int timeout = 1000;
//jedis客户端
Jedis jedis = new Jedis(host,port,timeout);
//认证
jedis.auth("123456");
//执行操作,保存值
jedis.set("username","wang da cui");
//获取值
String result = jedis.get("username");
System.out.print(result);
//关闭连接
jedis.close();
}
2.4.连接池的使用
如果直接使用 Jedis
链接Redis会造成频繁的Jedis对象创建和销毁,对性能会有很大的影响,所以我们会选择使用连接池来链接性能。原理同Mysql连接池
- 编写测试方法,使用
JedisPool
连接池对象
@Test
public void test()throws Exception{
//1 创建jedispool配置对象
JedisPoolConfig config = new JedisPoolConfig();
//2 做配置
//最大空闲连接数
config.setMaxIdle(2);
//最大链接对象数
config.setMaxTotal(10);
//链接超时时间
config.setMaxWaitMillis(1*1000);
//获取连接是测试连接是否畅通
config.setTestOnBorrow(true);
//3 创建jedispool连接池对戏
//参数:配置对象,redis主机地址 ,超时时间,密码
JedisPool pool = new JedisPool(config,"127.0.0.1",6379,1*1000,"123456");
//4 通过jedispool获取连接
Jedis jedis = pool.getResource();
//5 执行操作
jedis.set("age",10);
String result = jedis.get("age");
System.out.println(result);
// 6 释放连接 , 底层做了兼容,如果是连接池操作就是释放,如果是连接操作就是关闭
jedis.close();
// 7 摧毁连接池-如果是真正项目中它应该是一个受spring管理的单例
pool.destroy();
}
- 工具类封装:JedisPool应该是单例的(想想你的Mybatis的DataSource也只是创建了一个),为了方便使用,将
JedisPool
封装成工具。
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.util.Properties;
/**
* 获取连接池对象
*/
public enum RedisUtils {
//使用枚举实现单例
INSTANCE;
//连接池对象
private static JedisPool jedisPool = null;
static {
//初始化链接池
//1 创建连接池配置对象
JedisPoolConfig config = new JedisPoolConfig();
//2 进行配置-四个配置
最小连接数
config.setMaxIdle(1);
//最大连接数
config.setMaxTotal(11);
//链接最长等待时间
config.setMaxWaitMillis(10 * 1000L);
//测试连接时是否畅通
config.setTestOnBorrow(true);
String host = "127.0.0.1";
int port = 6379;
String password = "123456";
int timeout = 10000;
//创建连接池
jedisPool = new JedisPool(config, host,port,timeout, password);
}
//获取连接
public Jedis getSource() {
return jedisPool.getResource();
}
//关闭资源
public void closeSource(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
/**
* 设置字符值
* @param key
* @param value
*/
public void set(String key, String value) {
Jedis jedis = getSource();
jedis.set(key, value);
closeSource(jedis);
}
/**
* 设置字符值
* @param key
* @param value
* @param seconds :过期时间
*/
public void setex(String key,int seconds, String value) {
Jedis jedis = getSource();
jedis.setex(key,seconds, value);
closeSource(jedis);
}
/**
* 设置字符值
* @param key
*/
public String get(String key) {
Jedis jedis = getSource();
try {
return jedis.get(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeSource(jedis);
}
return null;
}
/* 设置
* @param key
* @param value
*/
public void set(byte[] key, byte[] value) {
Jedis jedis = getSource();
jedis.set(key, value);
closeSource(jedis);
}
/**
*
* @param key
* @return
*/
public byte[] get(byte[] key) {
Jedis jedis = getSource();
try {
return jedis.get(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeSource(jedis);
}
return null;
}
}
2.Jedis的API操作
使用jedis来操作redis的key和value,而value有很多种类型,和命令操作一样。
2.1.key的操作
System.out.println(jedis.keys("*")); //查看所有的key
2.2.String的操作
System.out.println(jedis.set("name","zhangsan"));//新增
System.out.println(jedis.get("name"));//获取
System.out.println(jedis.set("name","zhangsan1"));//修改
System.out.println(jedis.get("name"));//获取
System.out.println(jedis.del("name"));//删除
2.3.List的操作
jedis.lpush("students1","1","2","3","5","6"); //添加数据
System.out.println(jedis.lrange("students1", 0, 3)); //获取数据
- 排序操作,对于数字元素排序不需要加
SortingParams
,对于字符串需要指定SortingParams
,并且指定使用assii值排序
// 对数字排序
jedis.flushDB();
//添加数据
jedis.lpush("nums","1","2","3","4","8","5","3","1");
//排序
System.out.println(jedis.sort("nums"));
//指定排序方式
SortingParams sortingParams1 = new SortingParams();
sortingParams1.desc();
System.out.println(jedis.sort("nums", sortingParams1));
//对字母排序
jedis.lpush("langues","java","php","c++","test","ui");
SortingParams sortingParams = new SortingParams();
sortingParams.alpha();
sortingParams.desc();
System.out.println(jedis.sort("langues",sortingParams));
2.4.Set的操作
jedis.sadd("students2","a1","b1","c1","b1"); //添加数据
System.out.println(jedis.smembers("students2")); //获取成员
2.5.Hash操作
jedis.hset("students3","student","zhangsan"); //添加数据
System.out.println(jedis.hget("students3", "student")); //获取数据
2.6.事务操作
jedis.set("name","zs");
jedis.set("age",18);
//开启事务
Transaction multi = jedis.multi();
multi.incr("name");
multi.incr("age");
//提交事务
List<Object result = multi.exec();
System.out.println(result);
//关闭连接
jedis.close();
//关闭连接池
pool.destory();
```
### 3 springBoot spring data redis
> Spring data:spring对数据操作支持规范,但是我们的数据是多种类型,比如rdbms(msyql)、redis(Nosql)、es、mq
>
> Spring data redis :spring操作redis
>
> Spring data jpa :操作关系型数据库
>
> springBoot spring data redis:简化springdata对redis的配置
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<!--导入spring data redis 的jar包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
spring:
redis:
host: localhost
port: 6379
password: 123456
jedis:
pool:
max-idle: 8
max-active: 8
max-wait: 2000
五.Redis的持久化配置
1.Redis的持久化概念
1.1.什么是Redis持久化
因为Redis数据基于内存读写,为了防止Redis服务器关闭或者宕机造成数据丢失,我们通常需要对Redis最磁极化,即:把内从中的数据(命令)保存一份到磁盘做一个备份,当Redis服务关闭或者宕机,
在Redis服务器重启的时候会从磁盘重新加载备份的数据,不至于数据丢失。 Redis 提供了两种不同级别的持久化方式:RDB和AOF,可以通过修改redis.conf来进行配置.
开启持久配置后,对Redis进行写操作,在Redis安装目录将会看到持久文件:“appendonly.aof”和“ dump.rdb”。
1.2.Redis如何保存数据
redis为了考虑效率,保存数据在内容中.并且考虑数据安全性,还做数据持久化,如果满足保存策略,就会把内存的数据保存到数据rdb文件,还来不及保存那部分数据存放到aof更新日志中。在加载时,把两个数据做一个并集。
1.3.Redis持久化原理图
- 启动Redis载入持久化数据
1.3.Redis持久化-RDB
RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照,默认开启该模式
-
如何关闭 rdb 模式?修改配置文件注释如下内容
save “”
save 900 1 #至少在900秒的时间段内至少有一次改变存储同步一次
save xxx
save 60 10000
1.4.Redis持久化-AOF
AOF 持久化记录服务器执行的所有写操作命令
,并在服务器启动时,通过重新执行这些命令来还原数据集,默认关闭该模式。
-
如何开启aof模式?修改配置文件如下内容
appendonly yes #yes 开启,no 关闭
appendfsync always #每次有新命令时就执行一次fsync
appendfsync everysec #每秒 fsync 一次 ,这里我们启用 everysec
appendfsync no #从不fsync(交给操作系统来处理,可能很久才执行一次fsync)
其它的参数请大家看redis.conf配置文件详解
2.Redis持久配置
2.1.配置文件
-
见:redis.windows.conf 或者 redis.conf ,Redis 版本不一样配置文件名字不一样
- bind # 指定的ip才能访问
- port #默认端口
- timeout #连接超时
- loglevel #日志的级别
- logfile #日志文件输出路径
- databases #数据库数量
- save 900 1 #RDB持久方式,900 秒有一个数据修改进行持久化
- appendonly #AOF持久方式
2.2.Redis持久化配置
根据业务情况修改配置文件中的持久化配置项目即可
2.3.数据备份与恢复
虽然配置了持久化Redis会进行自动数据备份,我们也可以通过SAVE
或者 BGSAVE
(后台备份)命令创建当前数据库的备份
-
数据备份执行如下命令
save #该命令将在 redis 安装目录中创建dump.rdb文件。
-
恢复数据,将dump.rdb) 移动到 redis 安装目录并启动服务即可。
-
在Linux上获取 redis 目录可以使用 CONFIG 命令如:
CONFIG GET dir #返回:“/usr/local/redis/bin”
3.RDB和AOP区别
3.1.RDB
RDB持久化是指在指定的时间间隔
内将内存中的数据集快照
写入磁盘,实际操作过程是fork一个子进程
,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储 。
RDB优势如下:
1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件
,这对于文件备份
而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
2). 对于灾难恢复而言,RDB是非常不错的选择
。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
3). 性能最大化
。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高
。
RDB劣势如下:
如果你想保证数据的高可用性,即最大限度的避免数据丢失
,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时
,可能会导致整个服务器停止服务
几百毫秒,甚至是1秒钟。
3.2.AOF
AOF持久化以日志的形式记录服务器所处理的每一个写、删除
操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
AOF优势如下:
1). 该机制可以带来更高的数据安全性
,即数据持久性。
2). 由于该机制对日志文件的写入操作采用的是append
模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容
。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
3). 如果日志过大,Redis可以自动启用rewrite机制
。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
4). AOF包含一个格式清晰、易于理解
的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。
AOF的劣势如下:
1). 于相同数量的数据集而言,AOF文件通常要大于RDB文件
。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB
。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。不过生产环境其实更多都是二者结合使用的。
3.3.总结
RDB:记录数据快照
优点:
1.产生一个持久化文件,方便文件备份 , 灾难恢复RDB是非常不错的选择
2.Fork子进程去持久化, 性能比AOF好,文件体积更小,启动时恢复速度快
缺点:
1.没办法100%s数据不丢失
2.数据集大,FORk子进程持久化时会服务器卡顿
AOF: 记录写命令
优点:
1.数据更安全
2.采用Append,即使持久的时候宕机,也不影响已经持久的数据
3.日志过大,可以rewrite重写
4.AOF日志格式清晰,容易理解
缺点:
1.AOF文件通常要大于RDB文件
2.AOF数据恢复比RDB慢
最佳实践:二者结合 ,RDB来数据备份,迁移,容灾 。 AOF持久化保证数据不丢失。
六.Redis的淘汰策略
1.淘汰策略基本概念
1.1.为什么要淘汰
Redis的数据读写基于内存,Redis虽然快,但是内存成本还是比较高的,而且基于内存Redis不适合存储太大量的数据。Redis可以使用电脑物理最大内存,当然我们通常会通过设置maxmemory
参数现在Redis内存的使用, 为了让有限的内存空间存储更多的有效数据,我们可以设置淘汰策略,让Redis自动淘汰那些老旧的,或者不怎么被使用的数据。
redis 确定驱逐某个键值对后,会删除这个数据,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)。
2.2.淘汰策略有哪些
- volatile-lru :从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-enviction(驱逐):禁止驱逐数据
2.淘汰策略配置
2.1.最大内存配置
-
修改配置redis.windows.conf,修改maxmemory,放开注释, 根据情况设置大小
maxmemory <bytes
2.2.淘汰策略配置
-
修改配置redis.windows.conf ,修改maxmemory-policy ,放开注释,按情况修改策略
maxmemory-policy noeviction #noeviction 为默认的策略,根据情况修改