NoSQL(Not Only SQL)泛指非关系型数据库。
NoSQL不依赖业务逻辑方式存储,而以简单的Key-value模式存储,因此大大增加了数据库的扩展能力
不遵循SQL标准
不支持 ACID
远超于SQL的性能
1.对数据高并发的读写
、
2.海量数据的读写
3.对数据高扩展性的
1.需要事物支持
2.基于sql的结构化查询存储,处理复杂的关系需要即席查询
总结!用不着sqll 和用了sql也不行的清空,请考虑 NoSql
1,Memcache
2.Redis
3.MongoDB
Redis 是一个开源的key-value存储系统
和Memcached类似,它支持存储的value类型相对更多,包括 string (字符串),list(链表),set(集合), zset(sorted set --有序集合)和 hash(哈希类型)
这些数据类型都支持 push/pop add/remove 及取交集并集和差以及更丰富的操作,而且这些操作都是原子性的
在此基础上,Redis支持各种不同方式的排序
与Memcached一样,为了保证效率,数据都是缓存在内存中。
区别是Redis会周期性的把更新的数据写入磁盘,或者把修改操作写入追加的记录文件
并且在此基础上实现了 master-slave(主从)同步
高频词,热门访问的数据,降低数据库IO
分布式架构,做session共享
默认端口6379
默认16个数据库,类似数组下标从0开始,初始默认使用0号库
使用命令select index 来切换数据库
所有库的密码相同
dbsize 查看当前数据库key的数量
flushdb清空当前库
flushall 通杀全部库
Redis 是单线程+多路IO复用技术
例子:好几个人让同一个黄牛帮忙买票,在没买到的时候这几个人可以做其他事情
keys*查看当前所有key
exists key 判断某个key是否存在
type key 查看你的key是什么类型
del key 删除指定的key数据
unlink key 根据value 选择非阻塞删除
仅将keys 从 keyspace元数据中删除,真正的删除会在后续异步操作。 也就是执行后就显示删除成功但是数据是慢慢删除的
expire key 为给定的key设置过期时间
ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已经过期
select 切换库
String 是Redis最基本的类型,一个key对应一个value
String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片 或者序列化的对象
String 类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M
set
若设置相同的key 后者的value会把前者覆盖
get< key > 获取值
append< key >< value > 将指定的value值追加到原值的末尾
strlen < key >获得值的长度
setnx
incr< key >
将key中存储的数字值增1
只能对数字值操作,如果为空,新增值为1
decr < key >将key中储存的数字值减1
incrby/decrby < key> <步长>将key中储存的数字增减,自定义步长
mset< key1>< value1>< key2>< value2>同时设置一个或多个 key-value对
mget< key1>< key2>< key3> 同时获取一个或多个value
msetnx < key1>< value1>< key2>< value2> 同时设置多个 key-value对,当且仅当所有给定的key都不存在
原子性,有一个失败则都失败
getrange < key> <起始位置><结束位置> 获得值的范围,类似于java中的substring 前包,后包
setrange < key ><起始位置>< value> 用< value> 覆写< key>所存储的字符串值,从< 起始位置>开始 (索引从0开始)
setex < key><过期时间> < value> 设置键值的同时,设置过期时间,单位秒
getset< key>< value> 以新换旧 设置了新值的同时获得旧值
String的数据结构为简单动态字符串。是可以修改的字符串,内部结构类似于java中的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。
单键多值 Redis列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素导列表的头部或者尾部,它的底层是双向列表,对两端的操作性能很高,通过索引下表的操作中间的节点性能会较差。
lpuah/rpush < key>< value1>< value2> < value3> 从左边/右边插入一个或多个值
lpop/rpop < key> 从左边/右边吐出一个值。 值在键在,值亡键亡
rpoplpush < key1> < key2> 从 < key1>列表右边吐出一个值,插到< key2>列表左边
lrange< key> < start> < stop? 按照索引下标获得元素 从左到右
lindex < key> < index> 按照索引下标获得元素(从左到右)
llen < key> 获得列表长度
linsert < key> before < value> < newvalue> 在< value>的前面插入 < newvalue>插入值
lrem < key> < n> < value> 从左边删除n和value 从左到右
lset < key>< index>< value>将列表key下标为index的值替换成value
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据使,se是一个很好选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Redis的set是string类型的无序集合。它底层其实是一个value为null的hash表 所以添加删除,查找的复杂度都是O(1)、
Redis hash 是一个键值对集合
Redis hash 是一个 string类型的 field
和value 的映射表,hash 特别适合用于存储对象。 类似Java里面的 Map
用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等新信息,如果用普通的key/value结构来存储
三种存储方式
通过 key +field 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。
Hash类型对应的数据结构是两种 当field-value长度较短且个数较少时,使用ziplist,否则使用 hashtable
在这里插入图片描述
vi /etc/redis.conf 保存 :wq!
配置大小单位,开头定义了一些基本的度量单位,支支持bytes,不支持bit 大小写不敏感
类似jsp中的include,多实例的情况可以把公用的配置文件提取出来
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub) 发送消息,订阅者(sub)接收消息
Redis客户端可以订阅任意数量的频道
1.打开一个客户端订阅 channel1频道
SUBSCRIBE channel1
2.打开另一个客户端,给channel1发布消息hello
publish channel1 hello
3.在订阅的客户端可以看到hello
命令:
命令
在这里插入图片描述
java 操作 Redis6
1.引入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.1.1</version>
</dependency>
1.创建Jedis对象
第一个参数是远程服务器地址,第二个是redis的端口号
测试一下
练习: 模拟验证码发送
1)输入手机号,点击发送后随机生成6位数字码,2分钟有效
2)输入验证码,点击验证,返回成功或失败
3)每个手机号每天只能发送3次验证码
1.可以利用 Random 生成 6位随机数字
2.把验证码放到redis里面,设置过期时间120秒
3.redis中取出验证码和输入的验证码进行比较
4. incr 每次发送之后加一 当值大于2时 提示不能进行发送
package com.ycx;
import redis.clients.jedis.Jedis;
import java.util.Random;
import java.util.Set;
public class JedisDemo1 {
public static void main(String[] args) {
//verifyCode("111","");
// Jedis jedis =new Jedis("47.113.230.41",6379);
// getRedisCode("111","274`199");
}
//1.生成六位验证码、
public static String getCode(){
Random random = new Random();
String code ="";
for (int i = 0; i < 6; i++) {
int rand = random.nextInt(10);
code+=rand;
}
return code;
}
//2.让每个手机每天只能发送三次,验证码放到redis中设置过期时间
public static void verifyCode(String phone,String code) {
Jedis jedis =new Jedis("47.113.230.41",6379);
String countKey = "Ver"+phone+":count"; //设置key的形式
String codeKey="ver"+phone+":code"; //设置key的形式
String count = jedis.get(countKey);
if(count==null){
//没有发送次数 ,第一次发送、
//设置发送次数为一
jedis.setex(codeKey,24*60*60,"1");
} else if(Integer.parseInt(count)<=2){
//发送次数加一
jedis.incr(codeKey);
} else if (Integer.parseInt(count)>2)
{
//发送三次,不能再放
System.out.println("今天发送次数已经超过三次");
jedis.close();
return;
}
String vcode=getCode();
jedis.setex(codeKey,120,vcode);
jedis.close();
}
//发送的验证啊放到redis中
//3 验证码校验
public static void getRedisCode(String phone,String code){
//从redis 获取验证码
Jedis jedis =new Jedis("47.113.230.41",6379);
String codeKey="ver"+phone+":code";
String redksClode = jedis.get(codeKey);
if(redksClode.equals(code)){
System.out.println("成功");
}else {
System.out.println("失败");
}
jedis.close();
}
}
1.再pom.xml文件中引入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.再Springboot的配置文件中配置 redis
#Redis服务器地址
spring.redis.host=47.113.230.41
#Redis服务器连接端口
spring.redis.port=6379
#Redis数据库索引(默认位0)
spring.redis.database=0
#连接超时时间(毫秒)
spring.redis.timeout=1800000
#连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=20
#最大阻塞等待时间(复数表示没有限制)
spring.redis.lettuce.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=5
#连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
3.添加Redis配置类
报错得化去添加json的配置文件
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setConnectionFactory(factory);
// key序列化方式
template.setKeySerializer(redisSerializer);
// value序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
// value hashmap序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// 解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
package com.ycx.redis_1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("test")
public class controller {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping
public String testRedis(){
redisTemplate.opsForValue().set("name","lucy"); //设置值导redis
String name = (String) redisTemplate.opsForValue().get("name");
return name;
}
}