狂神聊Redis
狂胜Redis课程安排:
- nosql 讲解
- 阿里巴巴架构演进
- nosql 数据模型
- Nosql 数据分类
- CAP
- BASE
- Redis入门
- Redis安装(Windows & Linux) 服务器
- 五大基本数据类型
- String
- List
- Set
- Hash
- Zset
- 三种特殊数据类型
- geo
- hyperloglog
- Bitmap
- Redis 配置详解
- Redis 持久化
- RDP
- AOF
- Redis 事务操作
- Redis 实现订阅发布(消息队列)
- Redis 主从复制
- Redis 哨兵模式 (现在公司中所有的集群都在用哨兵模式)
- 缓存穿透及解决方案
- 缓存击穿及解决方案
- 基于APIJedis讲解
- SpringBoot集成Redis操作
- Redis 实践分析
Nosql概述
为什么要用Nosql
我们生活在大数据时代,一般的数据库无法进行分析处理了 !
1, 单机Mysql的时代 !
2, Memcached (缓存) + Mysql + 垂直拆分 ( 读写分离)
3, 分库分表 + 水平拆分 + Mysql集群
4,如今的最近的年代
目前最基本的一个互联网项目:
为什么要用NoSql
什么是Nosql
Nosql
Nosql = not Only Sql ( 不仅仅是Sql )
关系型数据库 : 表 , 行 , 列 (POI)
泛指非关系型数据库 , 随着Web 2.0 互联网的诞生 ! 传统的关系型数据库 , 很难对付Web 2.0 时代,
尤其是超大规模的高并发的社区 ! 暴露出来很多难以克服的问题 , NoSql 在当今大数据环境下发展的十分迅速 , Redis是发展最快的,是我们当下必须要掌握的技术
Nosql的特点
解耦
1, 方便扩展( 数据之间无关系 ,很好的扩展)
2, 大数据量高性能 ( Redis 一秒可以写8万次 读可以读11万次 ,Nosql 的缓存记录级 , 是一种细粒度的缓存 , 性能会比较高)
3, 数据类型是多样型的 ( 不需要事先设计好数据库 ! 随取随用 ! 如果是一个十分大的表 , 很多人都无法设计了 ! )
4, 传统的RDBS 和 NoSql 的区别
传统的RDBS
-- 结构化组织
-- SQL
-- 数据和关系都存放在单独的表中
-- 数据操作 , 数据库定义语言
-- 严格的一致性
-- 基础的事务操作
-- ......
Nosql
--- 不仅仅是数据库
--- 没有固定的查询语言
--- 键值对存储 , 列存储 , 文档存储 , 图形数据库( 社交关系 )
--- 最终一致性
--- CAP定理 和 BASE 理论 ( 异地多活 ) 初级架构师 ! ( 狂神理念 : 只要学不死 , 就往死里学)
--- 高新能 , 高可用 , 高可扩
---.........................
了解: 3v + 3高
大数据时代的3v : 主要是描述问题的
大数据时代的3高 : 主要是对程序的要求
真正在公司中的实践 : Nosql + RDBMS 一起使用才是最强的 , 阿里巴巴的架构演进
技术没有高低之分 , 就看你如何使用 ! (提升内功,思维的提高)
Nosql的四大分类:
KV键值对:
文档型数据库:
列存储数据库:
图关系数据库:
Redis入门
Redis概述
Redis是什么
Redis能干吗?
特性
学习中用到的东西
Windows下安装
Linux下安装
官网下载最新的Redis , 利用软件将文件存在 opt 文件夹下解压
解压命令 :
tar xzf redis-6.2.6.tar.gz
13.后面我们会使用单机多Redis启动集群测试!
测试性能
基础的知识
Redis是单线程的!
redis的五大数据类型
官网文档
Redis-key
exists key
:判断键是否存在del key
:删除键值对move key db
:将键值对移动到指定数据库expire key second
:设置键值对的过期时间type key
:查看value的数据类型
# 查看所有key
keys *
# set key
set name kuangshen
# 判断当前key是否存在
exists name
# 移除当前Key
move name 1
# 设置key的过期时间
expire name 10
# 查看当前key的剩余时间
ttl name
# 查看当前key的一个类型
type name
关于TTL命令
Redis的key,通过TTL命令返回key的过期时间,一般来说有3种:
当前key没有设置过期时间,所以会返回-1.
当前key有设置过期时间,而且key已经过期,所以会返回-2.
当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.
关于重命名RENAME和RENAMENX
RENAME key newkey修改 key 的名称
RENAMENX key newkey仅当 newkey 不存在时,将 key 改名为 newkey 。
更多命令学习:https://www.redis.net.cn/order/
————————————————
版权声明:本文为CSDN博主「每天进步一點點」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/DDDDeng_/article/details/108118544
String( 字符串 )
90% 的 java 程序员使用 redis 只会使用 String类型!
# 追加字符串,如果当前key不存在,就相当于setkey
append key1 "hello"
# 获取字符串的长度
strlen key1
# 自增1
incr views
# 自减1
decr views
# 设置步长,指定增量
incrby views 10
# 设置步长,指定减量
decrby view 5
# 字符串范围 range
getrange key1 0 3
getrange key1 0 -1
# 替换
setrange key2 1 xx
# 设置过期时间
setex key3 30 "hello"
# 不存在才会进行设置
setnx mykey "redis"
数据结构是相同的!
String类型的使用场景 : value除了是我们的字符串还可以是我们的数字 !
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储 !
List
基本的数据类型
在redis里面 , 我们可以吧List 玩成 栈、队列、阻塞队列 !
所有的List命令基本上都是以L开头的
# 将一个值或多个值 , 插入到列表的头部 ( 左 )
# 将一个值或多个值 , 插入到列表的尾部 ( 右 )
# 移除列表的第一个元素
# 移除列表的最后一个元素
# 通过下标获得 list 中的某个值
# 返回列表的长度
# 移除指定的值
# 移除列表的最后一个元素 , 将他移动到一个新的列表中
# 将列表中指定下表的值替换为另外一个值 , 更新操作
# 将某个具体的值插入到某个值的前面或者是后面
小结 :
- 他其实是一个链表 , before node after , left , right 都可以插入值
- 如果key不存在 , 创建新的链表
- 如果key存在 , 新增内容
- 如果移除了所有的值 , 空链表 , 也代表不存在
- 在两边插入 , 或者是改动值 , 效率最高 ! 中间元素 , 相对来说效率会低一点 .
消息排队 ! 消息队列 ! ( Lpush Rpop ) , 栈 ( Lpush Rpop )
Set ( 集合 )
set 中的值是不可以重复的 !
# set 中添加元素
# set中查看指定set的所有值
# 判断某一个元素是否存在在set集合中
# 获取set集合中元素集合的个数
# 移除set集合中的指定元素
# 随机抽选一个set元素
# 随机抽选出指定个数的元素
# 删除指定key , 删除随机 key
# 将一个指定值移动到另外一个 set 集合
# 微博,哔哩哔哩 , 共同关注 ! ( 并集 )
- 差集
- 交集
- 并集
# 微博 , 将所有关注的人放在同一个集合里面 ! 将粉丝也放在集合中 !
共同关注 , 共同爱好 , 二度好友 , 推荐好友 ( 六度分割理论 )
Hash ( 哈希 )
Map 集合 , Key-Map ! 这时这个值是一个Map集合 ! Hash本质和String类型没有太大区别 , 还是一个简单的 Key-value !
# set 一个具体的 Key-Value
# set 多个具体的 Key-Value
# 获取多个字段值
# 获取全部数据
# 删除hash指定的Key字段 , 对应的value也会消失
# 获取Hash表的字段数量
# 判断Hash表中的指定字段是否存在
# 只获取所有的 Key 或者 Value
# 指定增量
# 如果不存在则可以进行设置 , 如果存在则不设置
hash 变更的数据 user name age , 尤其是用户信息之类的 , 经常变动的信息 ! hash 更适合于对象的存储 String 更适合字符串的存储 !
Zset ( 有序集合 )
在set的基础上添加了一个值
# 添加一个值
# 添加多个值
# 排序如何实现
# 移除元素
# 获取有序集合中的个数
# 获取指定区间的成员数量
其余的Api , 通过学习我们的学习 , 剩下的查询官方文档 !
三种特殊数据类型
geospatial 地理位置
朋友定位 , 附近的人 , 打车距离计算 .
Redis 的 Geo 在Redis 3.2 版本就推出了 ! 这个功能可以推算地理位置信息 , 例如两地之间的距离 , 方圆半径之内的人
只有六个命令
# getadd 添加地理位置
# getpos 获取指定城市的精度和维度
获得当前定位 : 一定是一个坐标值
# geodist
两个人之间的距离 !
单位 :
- m 单位为米
- km 为千米
- mi 为英里
- ft 为英尺
# georadius 以给定的经纬度为中心 , 找出某一半径内的元素
找附近的人 ? ( 获得所有附近的人的地址 , 定位 ! ) 通过半径来查询 !
获取指定数量的人 , 200
所有的数据都应该录入 : China : city 里面 , 才会让结果更加精确 !
# georadiusbymember 找出指定元素周围的其他元素
# geohash 命令 , 返回一个或者多个位置元素的geohash 表示
该命令将返回11个字符串的GeoHash字符串 !
GEO底层的实现原理其实就是Zset ! 我们可以使用Zset命令操作GEO !
HyperLogLog
什么是基数 ?
是可以有误差的 !
简介 :
Redis 2.8.9 版本就更新了 HyperLogLog 数据结构 !
Redis Herperloglog 基数统计的算法 !
优点 : 占用内存是固定的 , 2^64 不同元素的技术 , 只需要费12kb的内存 ! 如果要从内存的角度比较的话 , HerperLoglog 就是首选 !
网页的UV ( 一个人访问一个网址 , 还是算作一个人 )
传统的方式 , set 保存用户的 ID 然后就可以统计set中的元素数量 , 作为标准判断 ! 这个方式如果保存大量的用户 ID , 就会比较麻烦 . 我们的目的是为了计数 , 不是为了保存用户的ID
缺点 : 大概会有 0.81% 的错误率 ! 统计UV的业务 , 可以忽略不记得 .
测试使用
# 创建第一组元素
# 统计元素的基数数量
# 合并两组 ( 并集 )
Bitmap
位存储
统计用户信息 , 活跃不活跃 ,登录未登录 , 打卡全年打卡 , 两个状态的 , 都可以使用 Bitmap
Bitmap 位图 , 数据结构 ! 都是操作二进制位来进行记录 , 非0即1 .
测试
查看某一天是否打卡 !
统计打卡的天数 !
事务
Redis 事务本质 : 一组命令的集合 ! 一个事务中的所有的命令都会被序列化 , 在事务的执行过程中 , 会按照顺序执行 ! 一次性 , 顺序性 , 排他性 ! 执行一系列命令 !
==Redis 事务没有隔离级别的概念==
所有的命令在事务中 , 并没有直接执行 , 只有发起执行命令的时候才会执行 !Exec
Redis单条命令是保证原子性的 , 但是事务不保证原子性 !!!
Redis 的事务 :
- 开启事务 ( multi )
- 命令入队 ( ... )
- 执行事务 ( exec )
正常执行事务 !
放弃事务
编译异常 ( 代码有问题 ! 命令有错误 ! ) , 事务中的命令不会被执行 !
运行时异常 ( 例如 1/0 ) , 如果事务队列中存在语法性错误 , 那么在执行的时候其他的命令是可以正常执行的 , 错误即抛出异常
监控 ! Watch
悲观锁 :
- 很悲观 , 认为什么时候都会出问题 , 无论做什么都会加上锁 !
乐观锁 :
- 很乐观 , 认为什么时候都不会出现问题 , 无论做什么都不会加上锁 ! 在更新数据的时候就会去判断一下 , 是否有人修改过这个数据 , ( 例如MySQL中的 version )
- 获取version 更新的时候会比较version
redis 的监视测试 , 事务一旦执行成功监控就会取消掉
正常执行成功
测试多线程修改值 , 使用 watch 可以当作是乐观锁操作 !
如果修改失败 , 获取最新的值就好 !
jedis
我们要使用java来操作jedis了
什么是 jedis ? jedis 是Redis 官方推荐的 java 连接的开发工具 ! 使用 Java 操作 Redis 的中间件 ! 如果你要使用 java 操作redis , 那么一定要对 jedis 十分的熟悉 !
1. 导入对应的依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<!-- 导入Jedis jar包 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.0-m1</version>
</dependency>
<!-- fastjson jar包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
</dependencies>
2. 编码测试
- 连接数据库
- 操作命令
- 断开连接
Bug 解析 :
java 找不到目标类 , 此时勾选图下配置应该就可以了
连接测试成功:
输出PONG
常用的API:
String :
List :
Set :
Hash :
Zset :
基本API全部是上面所学习的
SpringBoot整合Redis
SpringBoot 操作数据 : SpringData , jpa , jdbc , mongodb , redis !
SpringData 和 SpringBoot 齐名的项目
说明 : 在SpringBoot 2.x之后 原来使用的 jedis被替换来了lettuce ?
jedis : 采用的是直连 , 多个线程操作的话 , 是不安全的 ,如果想要避免不安全的 , 使用jedis pool链接池 ! 更像BIO
lettuce : 采用netty , 实例可以再多个线程中进行共享 , 不存在线程不安全的情况 ! 可以减少线程数量 , 更像Nio模式
源码分析 :
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
) // 我们可以自定义一个 redisTemplate来替换这个默认的 !
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 默认的 RedisTemple 没有过多的设置 , redis 对象都是需要序列化的 !
// 两个泛型都是 Object, object 的类型, 我们后使用需要强制转换 <String , Object>
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean // 由于 String 是redis中最常用的类型 , 所以我们单独提出来了一个bean!
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
整合测试:|
1. 导入依赖
<!-- 操作redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置连接
# SpringBoot 所有的配置类 , 都有一个自动配置类 RedisAutoConfiguration
# 自动配置类都会绑定properties 配置文件 RedisProperties
spring.redis.host=172.0.0.1
spring.redis.port=6379
# 默认即0
spring.redis.database=0
3. 测试
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
// redisTemple 操作不同的数据类型 , api 和我们的指令是一样的
// redisTemple opsForValue 操作字符串 类似String类型
// redisTemple opsForList 操作List 类似List类型
// redisTemple opsForSet 操作Set 类似Set类型
// redisTemple opsForHash 操作Hash 类似Hash类型
// redisTemple opsForZSet 操作ZSet 类似ZSet类型
// redisTemple opsForGeo 操作Geo 类似Geo类型
// redisTemple opsForHyperLogLog 操作HyperLogLog 类似HyperLogLog类型
redisTemplate.opsForValue();
// 除了我们最基本的操作 , 我们常用的方法都可以直接通过redisTemplate操作 , 比如说事务, 和基本的CRUD
// 获取redis的连接对象
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.flushDb();
connection.flushAll();
}