一.Redis概念:
1.1什么是Redis:
Redis 是一个高性能的开源的、C语言写的Nosql(非关系型数据库),数据保存在内存中。redis严格上不是一种数据库,应该是一种数据结构化存储方法的集合。
1.2什么是非关系型数据库(NOSQL):
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,它泛指非关系型的数据库。
非关系型数据库和传统的关系型数据库不一样。不一定遵循传统数据库的一些基本要求,比如说,不遵循sql标准,事务,表结构等等,
1.3非关系型数据库(NOSQL)的分类:
1.4Redis和Mysql的区别:
类型:Redis是非关系型数据库,Mysql是关系型数据库
储存位置:Redis是粗存在内存中,Mysql是存储在磁盘中
存储过期:Redis支持储存过期,Mysql不支持存储过期
读写能能力:Redis非常高,Mysql很低
1.4 Redis的使用场景:
1.用作中央缓存:对于经常使用的数据,和高频数据可以存放在redis中,大大提高读写能力,类似Mybatis的二级缓存
2.用作计数器:网站的总访问量,注册人数,可能会发生高并发,我们就可以使用redis然后等在一个时间点把数据同步到关系型数据库中。
3.数据过期管理:我们可以在redis中配置数据过期时间,可以应用在验证码,红包,优惠卷登场景
4.实施攻防系统:我们可以在redis中存储同一ip地址,如果对方是使用暴力破解的方式,就会在同一时间大量的访问,我们可以控制同一ip的访问次数,达到安全控制。
5.队列系统:使用场景例如秒杀活动,我们可以将资格放入内存队列(redis)中,达到预防高并发的效果
6.消息订阅:Pub/Sub 构建实时消息系统 Redis 的 Pub/Sub 系统可以构建实时的消息系统,比如很多用 Pub/Sub 构建的实时聊天系统 的例子。如QQ群
7.自动去重:reids存储数据中有set数据结构,set是一个无序的,不可重复的集合,我们可以将要去重的数据存在redis的set中,达到去重的目的。
第一部分总结:从认识了解来看,Redis其实不是很难,我们现在已经有一个大致的了解,现在开始我们就要去实践一下,看看这个东西到底怎么用!
二:Redis的安装:
1.1 下载和安装:
下载地址:redis下载地址:http://redis.io/download ; http://redis.cn/
1.2 解压运行
直接win+r启动cmd控制台将redis服务器端拖到黑窗口,输入空格再将redis服务器配置拖到黑窗口回车即可;
看到上面的图片的界面,那么恭喜你,redis服务器就启动成功了!接着双击redis客户端应用,你会看到你的本机ip加上redis的端口号,那么现在我们就可以操作redis了!
三:Redis的命令入门:
首先我们知道redis可以操作很多数据类型,上面已经说到过了,包括string(字符串)、list(链表)、set(集合)、 zset(sorted set --有序集合)和hash(哈希类型)
1. 操作String类型的命令:
redis是key-value Nosql,我们能操作就只有key,以及各种类型vaule.按照规范我们应该先设置密码,客户端访问之前应该先确定密码,我在后面会给大家讲到如何设置密码。
- 1.将一个key和一个value存在redis中
set name zs //name为key zs为value
- 2.通过key在redis中取值
get name
- 3.在redis中存储多个键值对
mset name zs age 18 //设置两个字符串键值对
- 4.通过多个key在redis中取值
mget name age //获取key的name和age的值
- 5.将储存的key的值自增1
incr age // 将age的值自增1
- 6.将存储的key的值自减1
decr age //将age的值自减1
- 7.将存储的key的值自增指定数
incrBy age 5 // 将age的值自增5
-8.将存储的key的值自增指定数
decrBy age 5 // 将age的值自减5
- 9.查看所有的key
keys * //查看所有的属性
- 10.删除指定的某个key
del name //删除key为name的值
- 11.设置key的过期时间(secnods秒后过期)
expire name 10 // 设置name的过期时间是10秒后
- 12.查看key的过期时间
ttl name //查看name的过期时间
- 13.清空整个redis服务器数据,所有的数据库全部清空
flushall
- 14.清除当前库
flashdb
- 15.选择数据库,redis中默认有16个数据库,名称分别为0,1,2,15 , index数据库索引
select 0 //查看索引为0的数据库
2.操作List类型的命令:
- 将一个或多个值 value 插入到列表 key 的表头(最左边)
lpush name zs ls //在key为name的list中存zs和ls两个值
- 返回列表 key 中指定区间内的元素,查询所有的stop为-1即可
lrange name 0 -1 //查询所有
lrange age 0 2 //查询索引在0到2之间的所有元素
- 将一个或多个值 value 插入到列表 key 的表尾(最右边)
rpush name zs ls//从右往左插入
- 移除并返回列表 key 的头(最左边)元素
lpop name
- 移除并返回列表 key 的尾(最右边)元素。
rpop name
- 根据count值移除列表key中与参数 value 相等的元素count 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。count = 0 : 移除表中所有与 value 相等的值。
lrem name 1 ls //删除names列表左面第一个ls值
lrem name 0 ls //删除names列表中所有的ls值
lrem name -1 ls//删除names列表中右边第一个ls值
- 返回列表 key 中,下标为 index 的元素
lindex name 1 //返回name列表中的下标为1的元素
- 对一个列表进行修剪 ,保留范围内的,范围外的删除
ltrem name 0 2 //保留name列表下标为0到2之间的元素
3.操作set的命令:
set集合是一个无序的不含重复值的队列
- 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略
sadd name zs ls ws ls //去重之后是 zs ls ws
- 返回集合 key 中的所有成员
smembers names //获取说有元素
- 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略
srem names zs ls //删除names中的zs ls元素
- 返回集合存储的key的基数 (集合元素的数量).如果key不存在,则返回 0
scard name //返回这个集合中所有key的数量
4.操作Zset的命令:
ZSet(sorted sets)在Set基础上增加了“分数”,让set集合有了排序功能
- 将所有指定成员添加到键为key有序集合(sorted set)里面,如果指定添加的成员已经是有序集合里面的成员,则会更新改成员的分数(scrore)并更新到正确的排序位置
zsadd age 15 ls 19 wu
- 返回key的有序集元素个数。key存在的时候,返回有序集的元素个数,否则返回0
zcard age
- 返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员个数
zcount age 18 20 //获取age中年龄在18 到 20岁之间的元素个数
注意下面俩个api适用于5.0版本
- 删除并返回有序集合key中的最多count个具有最高得分的成员。如未指定,count的默认值为1
zpopmax age 2 //删除年龄最大的2个元素
- 删除并返回有序集合key中的最多count个具有最低得分的成员。如未指定,count的默认值为1。
zpopmin age 2 //删除年龄最小的两个元素
- 返回存储在有序集合key中的指定范围的元素。 返回的元素可以认为是按得分从最低到最高排列。 如果得分相同,将按字典排序。返回给定范围内的元素列表(如果指定了WITHSCORES选项,将同时返回它们的得分)。
zrange age 15 18 withscores //返回年龄在15 到 18 范围的元素,按从小到大的顺序,并且返回年龄
- 返回有序集key中成员member的排名。其中有序集成员按score值递增(从小到大)顺序排列。排名以0为底,也就是说,score值最小的成员排名为0。
zrank age ls //返回ls在age集合中的排名从小到大
- 返回有序集key中成员member的排名,其中有序集成员按score值从大到小排列。排名以0为底,也就是说,score值最大的成员排名为0。
zrevrank age ls //返回ls在age集合中的排名从大到小
- 返回有序集合中指定分数区间内的成员,分数由低到高排序,LIMIT控制分页
ZRANGEBYSCOREkey heights 0 170 WITHSCORES LIMIT 0 10 //查询heights中0-170分之间的元素,低到高排序,0条开始查询,每页10条
操作hash的命令
Hash类似于jdk中的Map,一个key下面以键值对的方式存储数据
- 设置 key 指定的哈希集中指定字段的值。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。如果字段在哈希集中存在,它将被重写。
hset user id 1 //给user这个key设置id=1键值对
- 获取hash类型的name键对应的值
hget user id //取userkey 中的id对应的值
- 批量添加name=value键值对到key这个hash类型
hmset user id 1 name ls //给user这个key设置id=1,name=ls多个键值对
- 批量获取hash类型的键对应的值
hmget user id name //获取多个值
- 返回哈希表 key 中的所有键
hkeys user //获取所有的字段名称
- 返回哈希表 key 中的所有值
hvals user
- 返回哈希表 key 中,所有的键和值
hgetall user
- 使用string结构
这个注意{ }里面存的是json字符串格式,我们要使用需要将格式转化
set user {id:1,name:ls}
四:设置密码操作:
通常设置密码的方式有两个,一个是通过命令的方式,第二种则是更改配置文件的方式。我们则建议使用更改配置文件的方式
五:Redis的事务操作:
首先,Redis是一个弱性事务的数据库,和刚性事务的数据库如Mysql不太一样,他没有事务特定的原则,一般选择金融类项目的时候不建议使用Redis。
Redis中的事务原理:
首先我们输入命令:multi,类似于commit.但是Redis的操作则是从multi开始记录你的操作命令,但是并没有执行,当你输入exec时开始逐一执行命令操作,当有一个操作报错,则不会回滚事务。结束事务的命令时discard(意思是取消之前的所有操作命令)
六:Redis的持久化配置:
1.什么是Redis的持久化:
因为Redis数据基于内存读写,为了防止Redis服务器关闭或者宕机造成数据丢失,我们通常需要对Redis最磁极化,即:把内从中的数据(命令)保存一份到磁盘做一个备份,当Redis服务关闭或者宕机,在Redis服务器重启的时候会从磁盘重新加载备份的数据,不至于数据丢失。 Redis 提供了两种不同级别的持久化方式:RDB和AOF,可以通过修改redis.conf来进行配置.开启持久配置后,对Redis进行写操作,在Redis安装目录将会看到持久文件:“appendonly.aof”和“ dump.rdb”。
2.Redis是如何保存数据的:
redis为了考虑效率,保存数据在内容中.并且考虑数据安全性,还做数据持久化,如果满足保存策略,就会把内存的数据保存到数据rdb文件,还来不及保存那部分数据存放到aof更新日志中。在加载时,把两个数据做一个并集。
3.Redis持久化-RDB:
- 下面的图中是900秒内,如果进行了写操作,就会同步快照进行备份
4.Redis持久化-AOF:
- 将该配置改为yes,则开启AOF持久化,默认情况是关闭的。
5.数据备份与恢复:
虽然配置了持久化Redis会进行自动数据备份,我们也可以通过SAVE 或者 BGSAVE (后台备份)命令创建当前数据库的备份
save //该命令将在 redis 安装目录中创建dump.rdb文件。
七:Redis的淘汰策略:
1.为什么需要淘汰策略:
Redis的数据读写基于内存,Redis虽然快,但是内存成本还是比较高的,而且基于内存Redis不适合存储太大量的数据。Redis可以使用电脑物理最大内存,当然我们通常会通过设置maxmemory参数现在Redis内存的使用, 为了让有限的内存空间存储更多的有效数据,我们可以设置淘汰策略,让Redis自动淘汰那些老旧的,或者不怎么被使用的数据.redis 确定驱逐某个键值对后,会删除这个数据并,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)。
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(驱逐):禁止驱逐数据
八:Java操作Redis
步骤:
- 开始在 Java 中使用 Redis 前, 我们需要确保已经安装并启动 redis 服务及 Java redis 驱动,且你的机器上能正常使用 Java。可以取Maven仓库下载驱动包 下载 jedis.jar
- 导入jar包或依赖
commons-pool2-2.2.jar #连接池
jedis-2.5.2.jar #Jedis核心包
- 编写测试类
@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();
}
- 可以抽成一个工具类
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;
}
}
- 可以通过工具类获取jedisPool来对redis进行操作
Redis的基本概念和常用api都已经总结出来了,下一章我们来说一下集群和分布式,谈一谈Redis集群的特性