1.分布式缓存Redis6安装
1.1.缓存和队列简介
高并发必备两大“核心技术”
(1)什么是队列(MQ消息中间件)
全称:MessageQueue,主要用于程序与程序之间的通信(异步+解耦)。 核心应用: (1)解耦:订单系统->物流系统 (2)异步:用户注册同时发送优惠劵,和初始化操作 (3)削峰:秒杀、日志处理
(2)什么是缓存
程序需要经常调用的数据放在内存中,因为内存中的响应非常快,使其快速调用,避免去数据库持久层去查。 主要就是提高性能 DNS缓存、前端缓存、代理缓存服务器Nginx、应用程序缓存、数据库缓存
1.2.本地缓存和分布式缓存介绍
(1)分布式缓存
与应用隔离的缓存组件或服务,与本地服务隔离的一个独立的缓存服务,多个服务可共享这一个缓存,多个节点共享缓存,需要考虑带宽。
常见的分布式缓存:Redis、Memcached
(2)本地缓存
和业务程序一起的缓存,例如mybatis的一二级缓存,只能由服务本身调用,不能多节点共享,不需要考虑带宽。
常见的本地缓存:guava、redis也可以做本地缓存、SpringCache
(3)本地缓存和分布式缓存的选择
结合业务去选择缓存,高并发的项目一般分布式缓存和本地缓存都存在。
(4)热点key的解决方案
热点key一般都放在本地缓存中,因为不需要带宽,效率很高,先去本地缓存中去查找,没有的话再去分布式缓存中查找。 应用:热点新闻、热卖商品、大V明星结婚
1.3.Nosql和Redis简介
- 什么是Redis
- 其两者最重要的区别是NoSQL不使用SQL作为查询语言。
- NoSQL数据存储可以不需要固定的表格模式
- 键 - 值对存储,列存储,文档存储,图形数据库
- NoSql:redis、memcached、mongodb、Hbase
一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API
高性能:Redis能读的速度是110000次/s,写的速度是81000次/s
内存中的存储结构,它可以做为消息中间件、缓存、数据库。如:lists(列表)、hashs(散列)、sorted sets(有序集合)、sets(集合)、strings(字符串)
1.4.Linux源码安装Redis6
(1)源码安装Redis上传到linux服务器(先安装升级gcc新版才能编译)
#安装gcc yum install -y gcc-c++ autoconf automake #centos7默认的gcc是4.8.5版本,版本小于5.3无法编译,要先安装gcc新版才能编译 gcc -v(查看gcc当前版本) #升级新版gcc,配置永久生效 yum -y install centos-release-scl yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils scl enable devtoolset-9 bash #从gcc4.8.5切换到gcc9编译器 echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile #解压redis安装包 tar -xvf redis.6.2.1.tar.gz mv redis.6.2.1 redis6 #编译redis cd redis6 make #安装到指定的目录 mkdir -p /usr/local/redis make PREFIX = /usr/local/redis install
- 注意:安装编译redis6需要升级gcc,默认自带的gcc版本比较老
- redis-server:redis启动文件
- redis-cli:redis客户端
- redis.conf:redis配置文件
1.5.Docker容器化部署Redis6
云计算+容器化是当下的主流,也是未来的趋势, docker就是可 以快速部署启动应⽤ 实现虚拟化,完整资源隔离,⼀次编写,四处运⾏ 但有⼀定的限制,⽐如Docker是基于Linux 64bit的,⽆法在 32bit的linux/Windows/unix环境下使⽤
(1)Docker安装
#安装并运行Docker yum install -y docker-io #启动docker systemctl start docker #检查安装结果 docker info #启动使用docker systemctl start docker #运行Docker守护进程 systemctl stop docker #停止Docker守护进程 systemctl restart docker#重启Docker守护进程 docker ps #查看容器 docker stop 容器id #停掉某个容器 #修改镜像文件 vim /etc/docker/daemon.json { "debug":true,"experimental":true, "registry-mirrors":["https://pb5bklzr.mirror.aliyuncs.com","https://hubmirror.c.163.com","https://docker.mirrors.ustc.edu.cn"] }
(2)Docker部署redis并配置密码
docker run -itd --name xdclass-redis -p 6379:6379 redis --requirepass 123456 -i:以交互模式运行容器,通常与-t同事使用。 -d:后台运行容器,并返回容器ID。
1.6.分布式缓存Redis6核心配置
(1)redis.conf配置文件的核心配置
daemonize yes #配置偶后台运行,默认是no bind ip号 #绑定指定ip访问,0.0.0.0是不限制,配置多个ip用空格隔开,bind 192.168.10.1 192.168.10.2 port 端口号 #端口号,默认6379 requirepass #密码配置 dbfilename #配置redis持久化文件名称 dir #配置redis持久化文件存储地址 save #配置redis持久化机制
(2)在redis安装目录创建log、data、conf目录
日志:/usr/local/redis/log 数据:/usr/local/redis/data 配置文件:/usr/local/redis/conf
(3)在/usr/local/redis/conf中创建自定义的配置文件
touch /usr/local/redis/conf/redis.conf
vi /usr/local/redis/conf/redis.conf
#任何ip都可以访问 bind 0.0.0.0 #守护进程 daemonize yes #密码 requirepass 123456 #日志文件 logfile "/usr/local/redis/log/redis.log" #持久化文件名称 dbfilename xdclass.rdb #持久化文件路径 dir "/usr/local/redis/data" #持久化策略,10s内有一个key改动,执行快照 save 10 1
(4)指定配置文件启动redis
/usr/local/redis/bin/./redis-server /usr/local/redis/conf/redis.conf
查看日志确定是否启动:tail -f /usr/local/redis/log/redis.log
2.分布式缓存Redis6数据结构
2.1.Redis6常见数据结构
(1)exists 判断key是否存在
exists name #判断name这个key是否存在
(2)del 删除key
del name #删除name这个key
(3)type 判断key的类型
type name #判断name是什么类型
(4)ttl 查看key的存活时间
ttl name #判断name还有多长时间过期 ttl age #判断age还有多长时间过期
2.2.Redis6数据结构之String类型
- 简介:存储字符串类型的key-value
- 应用场景:验证码、计数器、订单重复提交、用户登录信息、商品详情
常用命令:
(1)set/get 设置和获取key-value
设置key-value:set user:name lixiang 获取key:get user:name
(2)incr 对指定key的value进行自增1
incr user:age
(3)incrby 对指定key的value进行+n操作
incrby user:age 10
(4)mget/mset 一次获取多个key值,一次设置多个key-value
设置:mset user:addr tianjin user:phone 1333333333 获取:mget user:addr user:phone
(5)setex 设置一个key-value带有过期时间的
setex user:code 30 236589
(6)setnx 当key不存在时,才设置key-value,key存在时,不做操作
setnx user:name xxxxx
2.3.Redis6数据结构之List类型
- 简介:字符串列表,按照插入顺序排序,双向链表,插入删除时间复杂度为O(1)快,查找为O(n)慢。
- 应用场景:简单队列、最新商品列表、评论列表、非实时排行榜
- 常用命令:
(1)lpush 将一个或者多个值插入到列表头部,从左边开始插入
lpush phone:rank:daily iphone
(2)rpush将一个或者多个值插入到列表尾部,从右边开始插入
rpush phone:rank:daily xiaomi
(3)lrange获取指定key下边的范围元素,0代表第一个,1代表第二个,-1代表最后一个
lrange phone:rank:daily 0 -1
(4)llen获取当前key的元素个数
llen phone:rank:daily
(5)lindex获取当前索引元素的值
lindex phone:rank:daily 2
(6)lpop从顶部弹出一个元素,从左边弹出
lpop phone:rank:daily 1
(7)rpop从底部弹出一个元素,从右边弹出
rpop phone:rank:daily 1
(8)lrem 删除一个元素,可以指定移除个数
lrem word 2 a
(9)brpop移除并且获取列表的最后一个元素,如果列表没有元素会阻塞设置的时长或者在规定的时间内弹出元素为止
brpop word 10
2.4.Redis6数据结构之Hash类型
- 简介:Hash是一个string类型的field和value的映射表,hash特别适用于存储对象。
- 应用场景:购物车存储、用户个人信息存储、商品详情存储
- 注意:每个hash可以存储2[^32] -1 键值对(40多亿)
常用命令:
(1)hset/hget 设置和获取key中指定字段的值
设置key-value:hset product:daily:1 title iphone 获取key:hset product:daily:1 title iphone
(2)hdel 删除指定key的指定字段
hdel product:daily:1 title
(3)hmset/hmget 一次设置和获取多个key中指定字段的值
hmget product:daily:1 title color
(4)hgetall 获取指定key的全部字段的值
hgetall product:daily:1
(5)hincrby 对指定key的指定字段进行+n操作(n可以为正数也可以为负数)
hincrby product:daily:1 price 100
(6)hexists 判断指定key的指定字段是否存在
hexits product:daily:1 color
2.5.Redis6数据结构之Set类型
- 简介:将一个或者多个成员元素加入到集合中,已经存在的成员元素将被忽略
- 应用场景:去重、社交应用关注、粉丝、共同好友、大数据里面用户画像标签
常用命令:
(1)sadd添加一个或者多个指定的member元素到集合中,若集合中已存在元素,将被忽略
sadd user:tags:1 woman bwn 18-25 beijing
(2)smembers 获取当前集合中的所有元素
smembers user:tags:1
(3)srem 删除集合中某个元素
srem user:tags:1 bwn
(4)scard 返回集合中所有元素的个数
scard user:tags:1
(5)sismember 返回集合中是否存在当前元素
slsmember user:tags:1 bwn
(6)sdiff 返回两个集合中的差集
sdiff user:tags:2 user:tags:1
(7)sinter返回两个集合中的交集
siner user:tags:2 user:tags:1
(8)sunion 返回两个集合的并集
sunion user:tags:2 user:tags:1
2.6.Redis6数据结构之SortedSet类型
- 简介:用于将一个或者多个成员元素及分数值加入到有序集合中
- 应用场景:实时排行榜:商品热销榜、体育类应用热门球队、积分榜、优先级任务、朋友圈 文章点赞-取消
- 注意:底层采用Ziplist压缩列表和“跳跃表”两种存储结构,如果重复添加相同的元素数据,score值将被覆盖,保留最后一次修改的结果。
常用命令:
(1)zadd向有序集合中添加一个或者多个成员,或者更新已经存在的成员的分数
zadd video:rank 90 springcloud 80 springBoot 70 nginx 60 html 50 javascript 40 linux
(2)zcard获取有序集合中成员数
zcard video:rank
(3)zcount计算指定分数区间的成员的个数
zcount video:rank 0 50
(4)zincrby 有序集合中对指定的成员的分数+n(n可以为正数也可以为负数)
zincrby video:rank 5 linux
(5)zrange 返回索引区间的所有元素,从小到大
zrange video:rank 0 -1
(6)zrevrange返回索引区间的所有元素,从大到小
zrevrange video:rank 0 -1
(7)zrank 返回有序集合中指定成员的索引,从小到大返回
zrank video:rank 1
(8)zrevrank返回有序集合中指定成员的索引,从大到小排序
zrevrank video:rank 1
(9)zrem移除有序集合中的一个或者多个成员
zrem video:rank linux
(10)zscore返回有序集合中,成员的分数值
zscore video:rank springBoot
3.SpringBoot2.x整合Redis6客户端
3.1.分布式缓存Redis客户端讲解
- 自带客户端:redis-cli
- java语言客户端
- jedis
Jedis是直连模式,在多个线程间共享一个Jedis时是线程不安全的,需要使用连接池 其API提供了比较全面的Redis命令支持,相比其他Redis封装框架更加原生 Jedis中的方法调用是比较底层的暴漏的Redis的API,Java方法基本和Redis的API保持这一致 使用阻塞的I/O,方法调用同步,程序流需要等到socket处理完I/O才能执行,不支持异步操作
lettuce
高级Redis客户端,用于线程安全同步,异步响应 基于Netty的的事件驱动,可以在多个线程间并发访问, 通过异步的方式可以更好的利用系统资源
3.2.新版SpringBoot2.x项目创建
(1)相关软件环境
- JDK1.8+以上
- Maven3.5+
(2)加入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
注意:
- springBoot2后默认使用Lettuce作为redis的客户端
- 旧版本的Lettuce踩在堆外内存溢出的bug,5.3版本修复了 这个bug。
- 解决:升级版本或者换jedis
(3)SpringDataRedis的RedisTemplate介绍
- RedisTemplate介绍
- ValueOperations:简单K-V操作
- SetOperations:set类型数据操作
- ZSetOperations:zset类型数据操作
- HashOperations:针对map类型的数据操作
- ListOperations:针对List类型的数据操作
- RedisTemplate和StringRedisTemplate的区别
- StringRedisTemplate继承RedisTemplate
- 两者的数据是不互通的(默认的序列化机制导致key不一样)
- RedisTemplate默认采用的是JDK的序列化策略,会将数据先序列化成字节数组在存入Redis中
- 总结:
- 当Redis数据库里面操作的都是字符串数据的时候,那使用StringRedisTemplate即可
- 数据是复杂的对象类型,那么使用RedisTemplate是更好的选择
(4)Redis序列化和反序列化机制
- 同个key为啥获取不到值呢,核心就是序列化机制导致key值不一致
- 什么是序列化
- 把对象转化为字节序列的过程就称为对象的序列化
- 把字节序列恢复成对象的过程就是反序列化
- 对象字节序列化主要有两种用途
- 把对象的字节序列永久的保存在硬盘上,通常放在一个文件上
- 在网络上传输对象的字节序列
(5)Redis为什么要序列化
- 性能可以提高,不同的序列化方式性能不一样
- 可视化工具更好查看
- 采用默认的jdk方式会乱码(POJO类需要实现Serializable接口)
- 采用JSON方式则不用,且可视化工具更好的查看
(6)自定义Redis序列化方式,可以选择多种选择策略
- JdkSerializationRedisSerializer
- POJO对象的存存储场景,使用JDK本身序列化机制
- 默认机制ObjectInputStream/ObjectOutputStream进行序列化操作
- StringRedisSerializer
- key或者value为字符串
- Jackson2JsonRedisSerializer
- 利用jackson-json工具,将POJO实例序列化成json格式存储
- GenericFastJsonRedisSerializer
- 另一种javabean与json之间的转化,同时也需要指定Class类型
3.3.RedisTemplate序列化机制配置
@Configuration public class RedisTemplateConfiguration { /** * 自定义redisTemplate配置 * @param redisConnectionFactory * @return */ @Bean public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){ //默认使用JDK的序列化方式 RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); //使用Jackson2JsonRedisSerialize替换默认序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); //指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); //设置Key和Value的序列化规则 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); //设置hashKey和hashValue的的序列化规则 redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); //设置支持事务 //redisTemplate.setEnableTransactionSupport(true); //初始化RedisTemplate redisTemplate.afterPropertiesSet(); return redisTemplate; } }
3.4.Jedis+Lettuce客户端连接池配置
(1)lettuce连接池
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
(2)配置application.properties
#连接池最大连接数(使用负数表示没有限制) spring.redis.lettuce.pool.max-active = 10 #连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle = 10 #连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle = 0 #连接池最大阻塞等待时间(使用负数表示没有限制) spring.redis.lettuce.pool.max-wait = -1ms #指定客户端 spring.redis.client-type = lettuce
(3)配置application.yml
server: port: 8080 spring: redis: host: 8.140.116.67 port: 6379 password: 123456 client-type: jedis lettuce: pool: #连接池的最大连接数(负数表示没有限制) max-active: 10 #连接池中的最大空闲连接 max-idle: 10 #连接池的最小空闲连接 min-idle: 0 #连接池最大阻塞的等待时间(负数表示没有限制) max-wait: -1ms jedis: pool: #连接池的最大连接数(负数表示没有限制) max-active: 10 #连接池中的最大空闲连接 max-idle: 10 #连接池的最小空闲连接 min-idle: 0 #连接池最大阻塞的等待时间(负数表示没有限制) max-wait: -1ms
(4)Jedis连接池介绍(可以不排除lettuce依赖包)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <!-- 可以不排除lettuce依赖包 --> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <!--不用指定版本号,本身spring-data-redis里面有--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>