NoSQL介绍
NoSQL = Not Only SQL
为什么使用NoSQL 关系型数据库:表格,行,列 随着互联网的高速发展,传统的关系型数据库在应付超大规模,超大流量以及高并发的时候力不从心
大数据时代的3V和3高
大数据3V(问题)
海量Volume
多样Variety
实时Velocity
互联网3高(性能)
NoSQL特点
方便扩展(数据之间没有关系)
快速读写(Redis一秒写8万次,读取11万次)
成本低廉(大部分分布式数据库都是开源)
数据类型是多样型的(不需要事先设计数据库)
传统的RDBMS和NoSQL
传统的 RDBMS(关系型数据库管理系统)
结构化组织
SQL
数据和关系都在单独的表中
严格的一致性
基础的事务
。。。。。。
NoSQL
不仅仅是数据
没有固定的查询语言
键值对存储,列存储,文档存储,图形数据库(社交关系)
最终一致性
CAP定理和BASE(异地多活)
高性能,高可用,高可扩
。。。。。。
NoSQL类型 KV键值对
新浪:Redis
美团:Redis+Tair
阿里,百度:Redis+memecache
文档型数据库
MongoDB
MongoDB是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档
MongoDB是一个介于关系型数据库和非关系型数据库中中间的产品,MongoDB是非关系型数据库中功能最丰富,最像关系型数据库
ConthDB
列存储数据库
图形关系数据 社交关系,拓扑图
Redis 缓存 缓存就是数据交换的缓冲区(又称作Cache),当某一硬件要读取数据时,会首先从缓存中查找需要的数据,找到了则直接执行,找不到的话则从内存中查找。由于缓存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快地运行。
因为缓存往往使用的是RAM(断电即掉的非永久性储存),所以在用完后还是会把文件送到硬盘等存储器里永久存储。
概念 Redis(REmote DIctionary Server) 远程字典服务是一个由Salvatore Sanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从同步)。 它通常也被称为数据结构服务器
Redis能做什么
内存存储,持久化,内存中是断电即失,所以持久化很重要(rdb,aof)
效率高,可以用于告诉缓存
发布订阅系统
地图信息分析
计时器,计数器(浏览量)
。。。。。。
Redis基础知识 1 2 3 4 127.0.0.1:6379> select 3 OK 127.0.0.1:6379[3]>
1 2 3 127.0.0.1:6379[3]> keys * (empty list or set )
1 2 3 127.0.0.1:6379[3]> flushdb OK
1 2 3 127.0.0.1:6379[3]> flushall OK
Redis是单线程的 官方表示,Redis是基于内存操作,CPU不是Redis性能瓶颈,Redis的瓶颈是机器的内存和网络带宽。既然可以使用单线程,就是用单线程了。
误区
高性能的服务器一定是多线程的
多线程(CPU上下文会切换)一定会比单线程快
核心:Redis是将所有的数据全部存放在内存中,所以使用单线程去操作效率就是最高的,多线程(CPU会上下文切换:耗时),对于内存系统来说,如果没有上下文切换效率就是最高。
Redis-Key命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 127.0.0.1:6379> set 1 test1 OK 127.0.0.1:6379> set 2 test2 OK 127.0.0.1:6379> keys * 1) "2" 2) "1" 127.0.0.1:6379> exists 1 (integer ) 1 127.0.0.1:6379> exists 3 (integer ) 0 127.0.0.1:6379> move 1 1 127.0.0.1:6379> keys * 1) "2" 127.0.0.1:6379> expire 2 10 (integer ) 1 127.0.0.1:6379> ttl 2 (integer ) 0 127.0.0.1:6379> ttl 2 (integer ) -2 127.0.0.1:6379> type 1 string
Redis中文网文档
Redis事务 Redis事务本质:一组命令的集合。一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行。 一次性,顺序性,排他性
Redis事务没有隔离级别的概念。 所有的命令在事务中,并没有被直接执行。只有发起执行命令的时候才会执行。
Redis单条命令保证原子性,但是事务不保证原子性。
Redis事务:
开启事务(multi)
命令入队()
执行事务(exec)
命令
描述
MULTI
标记一个事务块的开始
EXEC
执行所有事务块内的命令
DISCARD
取消事务,放弃执行事务块内的所有命令
WATCH key [key …]
监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断(乐观锁 )
UNWATCH
取消 WATCH 命令对所有 key 的监视
正常执行事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> get k1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> exec 1) OK 2) "v1" 3) OK
放弃事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> set k4 v4 QUEUED 127.0.0.1:6379> discard OK 127.0.0.1:6379> get k4 (nil)
执行事务出错 编译型异常 代码错误,事务中所有命令都不执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> set k3 (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get k1 (nil)
运行时异常 如果事务队列中存在语法性错误,那么执行命令的时候,其他命令都是可以正常执行的,错误命令抛出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 127.0.0.1:6379> multi OK 127.0.0.1:6379> set k1 "v1" QUEUED 127.0.0.1:6379> incr k1 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> exec 1) OK 2) (error) ERR value is not an integer or out of range 3) OK 127.0.0.1:6379> get k2 "v2"
乐观锁 Redis可以用watch代替java中的乐观锁
性能测试 1 redis-benchmark [option] [option value]
可选参数:
来自Redis中文网
整合SpringBoot SpringBoot操作数据:Spring-data jpa jdbc mongodb redis
说明:在SpringBoot2.x之后,原来使用的jedis被替换为了lettuce jdis:采用直连,多个线程操作的话是不安全的,可使用jdis pool连接池避免安全问题。更像BIO模式 lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况。可以减少线程数据,更像NIO模式
RedisTemplate系统配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Bean @ConditionalOnMissingBean( name = {"redisTemplate"} ) public RedisTemplate<Object, Object> redisTemplate (RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }
步骤 导入依赖
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-pool2</artifactId > <version > 2.8.0</version > </dependency >
修改配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 spring.redis.database =0 spring.redis.host =localhost spring.redis.port =6379 spring.redis.lettuce.pool.max-active =10 spring.redis.lettuce.pool.max-wait =-1 spring.redis.lettuce.pool.max-idle =5 spring.redis.lettuce.pool.min-idle =1 spring.redis.timeout =3000
使用
1 2 3 4 5 redisTemplate.opsForValue(); redisTemplate.opsForHash(); redisTemplate.opsForList(); redisTemplate.opsForSet(); redisTemplate.opsForZSet();
操作与命令行操作一致
自定义配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Configuration public class RedisConfig { @Bean @SuppressWarnings("all") public RedisTemplate<String, Object> redisTemplate (RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); template.setConnectionFactory(factory); 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); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
参考
Redis数据类型