昆明公司网站制作,263企业邮箱登录官网,公司网站建设技术方案模板,dw做网站常用标签第一章 1、Redis概述 2、Mysql的演进 3、当今企业的架构分析 4、到底什么是nosql 5、阿里巴巴数据架构演进
第二章 6、NoSql四大分类 7、Redis概述 8、Windows安装redis…第一章 1、Redis概述 2、Mysql的演进 3、当今企业的架构分析 4、到底什么是nosql 5、阿里巴巴数据架构演进
第二章 6、NoSql四大分类 7、Redis概述 8、Windows安装redis 9、Linux安装Redis 10、Redis-benchmark性能测试
第三章 11、Redis基本说明 12、RedisKey命令 13、String字符串类型 14、List列表类型 15、Set集合类型
第四章 16、Hash类型 17、Zset有序集合 18、Geospatial地理位置 19、Hyperloglog技术统计 20、Bitmap位图场景
第五章 21、Redis事务 22、Redis乐观锁 23、Jedis操作Redis 24、Jedis事务 25、Springboot整合Redis
第六章 26、RedisTemlate 27、Redis配置文件 28、持久化RDB 29、持久化AOF 30、Redis订阅发布
第七章 31、Redis集群 32、主从复制 33、宕机后手动配置主机 34、哨兵模式 35、缓存穿透和雪崩 36、小结与拓展
**************************************************************************************************************************************************************
1、Redis概述
【1】学习方式上手就用。基本的理论学习融会贯通推荐这个。
【2】兴趣是最好的老师
【3】Nosql、五大数据类型、Redis配置和持久化
**************************************************************************************************************************************************************
2、单机Mysql的演进
【1】为什么要用Nosql
2020年大数据时代一般的数据库已经无法处理
【2】适者生存学习一个永久的技术
【3】单机Mysql的年代
【4】APP---DAL---Mysql
【5】静态网页Hao123Html服务器根本没有太多的压力
【6】瓶颈在哪里
数据量太大一个机器放不下
*****************************
数据的索引BTree一个机器的内存也放不下
*****************************
访问量读写混合一个服务器承受不了~
*****************************
只要你开始出现以上三种情况之一那么你就必须要晋级
【7】缓存mysql垂直拆分读写分离
网站80%的情况都是在读如果去查询数据库就会比较麻烦
我们希望减轻服务器眼里我们可以使用缓存来保证效率
【8】Cache
发展过程优化数据库结构和索引---文件缓存IO---Memcached当时最热门的技术**************************************************************************************************************************************************************
3、当今的企业架构分析
【1】分库分表水平拆分Mysql集群
一主二从
*****************************
后端越来越牛批
技术和业务发展的同时对人的要求也越来越高
【2】本质数据库的读写
早些年MyISAM表锁
转战Innodb行锁
慢慢使用分库分表来解决写的压力
Mysql推出了表分区并没有多少公司用
mysql集群很好的满足了年代的所有需求
【3】最近的年代
2010-2020十年之间世界发生了翻天覆地的变化
定位也是一种数据、音乐、热榜
mysql等数据库就不够用了数据量大变化很快
图型、JSON
mysql来存储一些比较大的文件博客图片数据库表很大效率就低
如果有一种数据库来专门处理这种数据mysql的压力就变小了
研究如何处理这些问题。
大数据IO压力下表几乎更大表几乎没法更大。
【4】互联网的架构模型 狂神还是可以的
【5】为什么用nosql
用户个人信息、社交网络、地理位置。用户自己产生的数据用户日志等爆发式增长
这时候我们就需要使用nosql数据库了nosql可以很好的处理以上的情况。**************************************************************************************************************************************************************
4、到底什么是nosql
【1】nosql 是指not only sql 不仅仅是sql
泛指非关系型数据库随着web2.0的诞生传统的数据库很难对付web2.0时代
尤其是超大规模的高并发的社区站长
暴露出来很多问题nosql在当今大数据环境下发展的十分迅速。
很多数据类型的结构不固定存储不需要一个固定的格式不需要多个操作就可以横向
扩展MapString,Object
【2】nosql的特点
方便扩展数据之间没有关系很好扩展
大数据量高性能reids一秒写8万次读取11万nosql的缓存记录级别是一种细粒度
的缓存性能会比较高
数据类型是多样型的不需要事先设计数据库随取随用如果数据量十分大的表很多人
就无法设计了。
传统的RDBMS和nosql。
nosql不仅仅是数据、没有固定的查询语言、键值对存储、文档存储、图形数据库、
最终一致性、CAP定理和BASE异地多活、高性能、高可用、高可扩展。
【3】3V3高
3V
海量Volume、多样Variety、实时Velocity
**********************
3高
高并发、高可扩、高性能
【4】真正在公司中的实践nosqlrdbms一起使用才是最强的。
技术没有高低之分就看你如何去使用提升内功思维的提高**************************************************************************************************************************************************************
5、阿里巴巴数据架构演进
【1】淘宝的数据难道都是在一个数据库里的吗
【2】阿里架构历程概述
1999年 Perl CGI Oracle
2000年进入java时代
2001-2004 EJB
2005-2007 springibatiswebx
2008-2009 Memcached集群mysql数据切分分布式存储Hadoop
2010 安全镜像nosql 秒杀 SSD
技术急不得越是慢慢学才能越扎实
【3】第五代网站架构的使命
敏捷开发、开放、体验
开源才是技术的王道
大量的公司做同样的业务随着这样的竞争业务是越来越完善的
【4】没有什么是加一层解决不了的
商品的基本信息可以用关系话数据库
商品的描述、评论文字比较多文档型数据库、MongDB
图片分布式软件系统 FastDFS 阿里云的OSS
商品的关键字搜索引擎 solr elasticsearch Isearch
商品的热门的波段信息内存数据库、Redis Tair、Memache...
商品的交易外部的支付接口三方应用
【5】大型互联网应用问题
数据类型太多了
数据源繁多经常重构
数据要改造大面积改造
【6】解决问题所有的经验来源于实战太对了卧槽
统一的数据服务层UDSL
UDSL热点缓存 设计**************************************************************************************************************************************************************
6、NoSql四大分类
【1】KV键值对
新浪Redis
美团RedisTair
阿里百度 RedisMemecache
【2】文档型数据库bson格式和json一样
MongoDB基于分布式文件存储的数据库用来处理大量的文档
MongoDB是一个介于关系型数据库和非关系型数据库中间的产品
ConthDB
【3】列存储数据库
HBase
分布式文件系统
【4】图形关系数据库
存关系的数据库它并不是存图形。比如社交网络、广告推荐
Neo4j InfoGrid
【5】敬畏之心可以使人进步宇宙是无限的科幻是玄妙的
努力学习、不断学习、才能跟上社会的步伐**************************************************************************************************************************************************************
7、Redis概述
【1】Remote Dictionary Server远程字典服务简称Redis
【2】能干什么
内存存储、持久化rdb aof
效率高可以用于高速缓存
发布订阅系统
地图信息分析
计时器、计数器浏览量
【3】特性
多样的数据类型
持久化
集群
事务
【4】所需材料
Redis官网 https://redis.io
Redis都推荐在Linux服务器上搭建我们是基于Linux学习**************************************************************************************************************************************************************
8、Windows安装redis
【1】Redis很小5M
【2】双击运行Redis服务即可
【3】端口是6379**************************************************************************************************************************************************************
9、Linux安装Redis
【1】下载安装包redis-6.0.6.tar.gz
【2】解压进入解压后的文件redis.conf
【3】基本环境安装yum install gcc-c
【4】make make install如果报错[rootlocalhost redis-6.0.1]# gcc -v # 查看gcc版本
[rootlocalhost redis-6.0.1]# yum -y install centos-release-scl # 升级到9.1版本
[rootlocalhost redis-6.0.1]# yum -y install devtoolset-9-gcc devtoolset-9-gcc-c devtoolset-9-binutils
[rootlocalhost redis-6.0.1]# scl enable devtoolset-9 bash
以上为临时启用如果要长期使用gcc 9.1的话
[rootlocalhost redis-6.0.1]# echo source /opt/rh/devtoolset-9/enable /etc/profile
————————————————
版权声明本文为CSDN博主「InTheWind1115」的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。
原文链接https://blog.csdn.net/weixin_44927585/article/details/108119203
【5】redis默认安装路径在/usr/目录下
和windows的目录一样/usr/local/bin
【6】把redis.conf拷贝到当前目录
cp /opt/redis/redis-6.0.6/redis.conf a_my_config
之后就使用这个配置文件
【7】启动redis默认不是后台启动
daemonize yes即可
【8】通过指定的配置文件启动服务
redis-server a_my_config/redis.conf #启动redis
进行连接测试set a b即可设置key value
redis-cli -p 6379进行访问
redis-cli shutdown # 停止redis**************************************************************************************************************************************************************
10、Redis-benchmark性能测试
【1】测试100并发10万个请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
【2】能够还看到多少秒内处理完毕所有请求**************************************************************************************************************************************************************
11、Redis基本说明
【1】Redis默认是16个数据库默认使用的是第0个
select xxx 可以切换数据库
DBSIZE 查看数据库大小
keys * 查看所有的key
【2】为什么redis端口号是6379
【3】Redis是单线程的Redis是根据机器的内存和网络带宽决定瓶颈的可以用单线程来做。
【4】为什么单线程还更快
redis是C语言写的官方提供的数据为10Wqps/秒不比Memechche差
********************************
误区一高性能的服务器一定是多线程的
误区二多线程一定比单线程效率高
CPU内存硬盘速度
核心redis所有的数据全部放在内存中所以使用单线程是效率最高的。
多线程CPU会有上下文切换耗时的操作对于内存系统没有CPU上下文切换效率是最高的**************************************************************************************************************************************************************
12、RedisKey命令
【1】五大数据类型他可以用于数据库、缓存、中间件
【2】keys *
EXISTS a
EXISTS b
move xxx 1
EXPIRE xxx 10 秒10后自动过期**************************************************************************************************************************************************************
13、String字符串类型
【1】90%的JAVA程序员使用redis仅用string类型
【2】常用命令
STRLEN xxx 长度
APPEN xxx YYY 拼接字符串
get xxx查看key值
set xxx yyy 设置值
incr xxx 给指定给key1
decr xxx 给指定的key-1
INCRBY xxx 10
DECRBY xxx 10
***********************************************
字符串范围
GETRANGE xxx 0 3 获取指定key的和指定范围
GETRANGE xxx 0 -1全部的字符串
SETRANGE xxx 1 yyy 从指定位置修改
setex 设置过期时间
setnx 不存在则设置
***********************************************
mset k1 v1 k2 v2 可以一次性设置多个值
mget k1 k2 k3
msetnx ... 批量设置不存在的key存储
***********************************************
set user:1 {xxxx:xxx,xxx:xxx} 设置usre:1对象
***********************************************
getset 先获取再设置
【3】作用设置计数器统计多单位的数量根据uid统计关注数量粉丝数对象缓存的存储
**************************************************************************************************************************************************************
14、List列表类型
【1】基本的数据列表
redis里list可以完成栈、队列、阻塞队列
LPUSH list 1
LPUSH list 2
LPUSH list 3
LRANGE list 0 -1 这个范围可以指定
RPUSH 从右侧添加
【2】redis不区分大小写命令
LPOP 从左侧移除
RPOP 从右侧移除
*******************************************
ltrim mylist 1 2通过下标截取list长度会改变原有key的值
lset
linsert
lrange
【3】list实际上是一个链表before node after left right都可以插入值
如果key不存在创建新的链表
如果key存在新增内容
如果移除了所有值空链表也代表不存在
两遍插入或者改动值效率最高
消息队列从左边进右边拿。**************************************************************************************************************************************************************
15、Set集合类型
【1】set中的值是不能重复的
【2】常用set命令
sadd myset hello
SMEMBERS myset
SISMEMBER myset hello
SISMEMBER myset world
SRANDOMEMBER myset 随机抽取一个元素
【3】删除指定key随机删除key
【4】共同关注并集**************************************************************************************************************************************************************
16、Hash类型
【1】Map集合key-Map集合
flushdb
【2】常见命令
hset myhash key1 value1
hget myhash key1
hmset 批量设置
hmget 批量获取
hgetall myhash
【3】hash本质和string类型没有太多区别还是一个简单的key value**************************************************************************************************************************************************************
17、Zset有序集合
【1】在set基础上加了一个值
zset k1 v1 score1
ZRANGESCORE salary -inf inf withscores 显示全部用户带成绩
【2】TopN**************************************************************************************************************************************************************
18、Geospatial地理位置
【1】朋友圈距离、附近的人、打车距离
GEOADD china:city 117 31 hefei
GEOADD china:city 121 31 shanghai
GEODIST chian:city hefei shanghai
geohash china:city xxx**************************************************************************************************************************************************************
19、Hyperloglog技术统计
【1】什么是基数
A {1 3 5 7 8 7}
B {1 3 5 7 8}
总计不重复的元素是5个
【2】数据结构统计网页UV
传统的方式set保存用户的id这种方式存储大量id会比较麻烦
Hyperloglog有0.81%的错误率
PFadd xxx xxx
PFCOUNT**************************************************************************************************************************************************************
20、Bitmap位图场景
【1】位存储
统计疫情人数0 1 0 1 0
统计用户信息活跃不活跃。登录、未登录打卡365打卡
setbit sign 0 1
setbit sign 1 0**************************************************************************************************************************************************************
21、Redis事务
【1】原子性要么同时成功要么同时失败
Redis是单条命令是保证原子性的
但是Redis事务是不保证原子性的
【2】事务的本质是一组命令的集合
一次性、顺序性、排他性
【3】Redis事务分为3个阶段
开启事务multi
命令入队set k1 v1...
执行事务exec
锁Redis可以实现乐观锁
【4】异常处理情况
编译型异常代码有错、命令有错事务中所有的命令都不会执行
运行时异常1/0事务队列中存在语法错误那么执行命令的时候其他正常命令是可以执行的**************************************************************************************************************************************************************
22、Redis乐观锁
【1】监控
悲观锁很悲观认为什么时候都会出问题很谨慎无论做什么都加锁
********************************
乐观锁很乐观认为什么时候都不会出问题所以不会上锁
获取version
更新的时候比较version
watch money
DECRBY in 20
incrby out 20
exec
测试多线程修改时使用watch可以当做redis的乐观锁操作
【2】redis-cli 连接本地redis客户端
auth [password] 输入redis密码**************************************************************************************************************************************************************
23、Jedis操作Redis
【1】使用Java操作Redis!-- https://mvnrepository.com/artifact/redis.clients/jedis --dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion4.2.3/version/dependency
【2】连接redis
package com.black.util;import redis.clients.jedis.Jedis;public class ZTest {public static void main(String[] args) throws Exception {Jedis jedis new Jedis(wdfgdzx.top, 6379);jedis.auth(s19911009!);System.out.println(jedis.ping());}
}**************************************************************************************************************************************************************
24、Jedis事务
【1】开启个事务体验下
package com.black.util;import org.json.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;public class ZTest {public static void main(String[] args) throws Exception {Jedis jedis new Jedis(wdfgdzx.top, 6379);jedis.auth(s19911009!);//****************************************************System.out.println(jedis.ping());jedis.flushDB();Transaction transaction jedis.multi(); // 开启事务JSONObject jsonObject new JSONObject();jsonObject.put(name, zs);jsonObject.put(age, 26);try {transaction.set(key1, jsonObject.toString());transaction.set(key2, jsonObject.toString());// int i 1 / 0;transaction.exec();} catch (Exception e) {transaction.discard();e.printStackTrace();} finally {System.out.println(jedis.get(key1));System.out.println(jedis.get(key2));jedis.close();}}
}**************************************************************************************************************************************************************
25、Springboot整合Redis
【1】SpringData JDBC redis...
!--Redis--
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependency
【2】jedis替换了lettuce为什么呢
jedis采用的是直连多线程操作是不安全的如果要避免需要使用jedis pool连接池
【3】自动配置类
package com.black.util;import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import javax.annotation.Resource;SpringBootTest(webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ZTest {Resourceprivate RedisTemplate redisTemplate;Testpublic void one() {redisTemplate.opsForValue().set(k1, v1);System.out.println(redisTemplate.opsForValue().get(k1));}
}
【4】自己可以做个性化定制配置RedisConfig**************************************************************************************************************************************************************
26、RedisTemlate
【1】实操存储可知所有的对象都需要序列化
User user new User();
user.setName(张三);
user.setNick(我的风格独自秀);
redisTemplate.opsForValue().set(user1, user);
System.out.println(redisTemplate.opsForValue().get(user1)); // 获取会报错
【2】用Redis.config配置具体的序列化方式
package com.black.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;Configuration
public class RedisConfig {// 这是我给大家写好的一个固定模板大家在企业中拿去就可以直接使用// 自己定义了一个 RedisTemplateBeanSuppressWarnings(all)public RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) {// 我们为了自己开发方便一般直接使用 String,ObjectRedisTemplateString, Object template new RedisTemplateString, Object();template.setConnectionFactory(factory);// Json序列化配置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);// String 的序列化StringRedisSerializer stringRedisSerializer new StringRedisSerializer();// key采用String的序列化方式template.setKeySerializer(stringRedisSerializer);// hash的key也采用String的序列化方式template.setHashKeySerializer(stringRedisSerializer);// value序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}
}
【3】然后再进行一波测试User都不用实现序列化了
User user new User();
user.setName(张三);
user.setNick(我的风格独自秀);
redisTemplate.opsForValue().set(user1, user);
System.out.println(redisTemplate.opsForValue().get(user1));
可以发现正常了
【4】企业开发中尽量分装utils用原生的操作有点麻烦
package com.black.util;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;//在我们真实的开发中, 或者你们在公司, 一般都可以看到一个公司自己封装redis的工具
Component
public final class RedisUtil {Autowiredprivate RedisTemplateString, Object redisTemplate;// common/*** 指定缓存失效时间** param key 键* param time 时间(秒)*/public boolean expire(String key, long time) {try {if (time 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据key 获取过期时间** param key 键 不能为null* return 时间(秒) 返回0代表为永久有效*/public long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}/*** 判断key是否存在** param key 键* return true 存在 false不存在*/public boolean hasKey(String key) {try {return redisTemplate.hasKey(key);} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除缓存** param key 可以传一个值 或多个*/
// SuppressWarnings(unchecked)public void del(String... key) {if (key ! null key.length 0) {if (key.length 1) {redisTemplate.delete(key[0]);} else {redisTemplate.delete((CollectionString) CollectionUtils.arrayToList(key));}}}// String/*** 普通缓存获取** param key 键* return 值*/public Object get(String key) {return key null ? null : redisTemplate.opsForValue().get(key);}/*** 普通缓存放入** param key 键* param value 值* return true成功 false失败*/public boolean set(String key, Object value) {try {redisTemplate.opsForValue().set(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 普通缓存放入并设置时间** param key 键* param value 值* param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期* return true成功 false 失败*/public boolean set(String key, Object value, long time) {try {if (time 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);} else {set(key, value);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 递增** param key 键* param delta 要增加几(大于0)*/public long incr(String key, long delta) {if (delta 0) {throw new RuntimeException(递增因子必须大于0);}return redisTemplate.opsForValue().increment(key, delta);}/*** 递减** param key 键* param delta 要减少几(小于0)*/public long decr(String key, long delta) {if (delta 0) {throw new RuntimeException(递减因子必须大于0);}return redisTemplate.opsForValue().increment(key, -delta);}// Map/*** HashGet** param key 键 不能为null* param item 项 不能为null*/public Object hget(String key, String item) {return redisTemplate.opsForHash().get(key, item);}/*** 获取hashKey对应的所有键值** param key 键* return 对应的多个键值*/public MapObject, Object hmget(String key) {return redisTemplate.opsForHash().entries(key);}/*** HashSet** param key 键* param map 对应多个键值*/public boolean hmset(String key, MapString, Object map) {try {redisTemplate.opsForHash().putAll(key, map);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** HashSet 并设置时间** param key 键* param map 对应多个键值* param time 时间(秒)* return true成功 false失败*/public boolean hmset(String key, MapString, Object map, long time) {try {redisTemplate.opsForHash().putAll(key, map);if (time 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张hash表中放入数据,如果不存在将创建** param key 键* param item 项* param value 值* return true 成功 false失败*/public boolean hset(String key, String item, Object value) {try {redisTemplate.opsForHash().put(key, item, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张hash表中放入数据,如果不存在将创建** param key 键* param item 项* param value 值* param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间* return true 成功 false失败*/public boolean hset(String key, String item, Object value, long time) {try {redisTemplate.opsForHash().put(key, item, value);if (time 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除hash表中的值** param key 键 不能为null* param item 项 可以使多个 不能为null*/public void hdel(String key, Object... item) {redisTemplate.opsForHash().delete(key, item);}/*** 判断hash表中是否有该项的值** param key 键 不能为null* param item 项 不能为null* return true 存在 false不存在*/public boolean hHasKey(String key, String item) {return redisTemplate.opsForHash().hasKey(key, item);}/*** hash递增 如果不存在,就会创建一个 并把新增后的值返回** param key 键* param item 项* param by 要增加几(大于0)*/public double hincr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, by);}/*** hash递减** param key 键* param item 项* param by 要减少记(小于0)*/public double hdecr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, -by);}// set/*** 根据key获取Set中的所有值** param key 键*/public SetObject sGet(String key) {try {return redisTemplate.opsForSet().members(key);} catch (Exception e) {e.printStackTrace();return null;}}/*** 根据value从一个set中查询,是否存在** param key 键* param value 值* return true 存在 false不存在*/public boolean sHasKey(String key, Object value) {try {return redisTemplate.opsForSet().isMember(key, value);} catch (Exception e) {e.printStackTrace();return false;}}/*** 将数据放入set缓存** param key 键* param values 值 可以是多个* return 成功个数*/public long sSet(String key, Object... values) {try {return redisTemplate.opsForSet().add(key, values);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 将set数据放入缓存** param key 键* param time 时间(秒)* param values 值 可以是多个* return 成功个数*/public long sSetAndTime(String key, long time, Object... values) {try {Long count redisTemplate.opsForSet().add(key, values);if (time 0) expire(key, time);return count;} catch (Exception e) {e.printStackTrace();return 0;}}/*** 获取set缓存的长度** param key 键*/public long sGetSetSize(String key) {try {return redisTemplate.opsForSet().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 移除值为value的** param key 键* param values 值 可以是多个* return 移除的个数*/public long setRemove(String key, Object... values) {try {Long count redisTemplate.opsForSet().remove(key, values);return count;} catch (Exception e) {e.printStackTrace();return 0;}}// list/*** 获取list缓存的内容** param key 键* param start 开始* param end 结束 0 到 -1代表所有值*/public ListObject lGet(String key, long start, long end) {try {return redisTemplate.opsForList().range(key, start, end);} catch (Exception e) {e.printStackTrace();return null;}}/*** 获取list缓存的长度** param key 键*/public long lGetListSize(String key) {try {return redisTemplate.opsForList().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 通过索引 获取list中的值** param key 键* param index 索引 index0时 0 表头1 第二个元素依次类推index0时-1表尾-2倒数第二个元素依次类推*/public Object lGetIndex(String key, long index) {try {return redisTemplate.opsForList().index(key, index);} catch (Exception e) {e.printStackTrace();return null;}}/*** 将list放入缓存** param key 键* param value 值*/public boolean lSet(String key, Object value) {try {redisTemplate.opsForList().rightPush(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存** param key 键* param value 值* param time 时间(秒)*/public boolean lSet(String key, Object value, long time) {try {redisTemplate.opsForList().rightPush(key, value);if (time 0) expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存** param key 键* param value 值* return*/public boolean lSet(String key, ListObject value) {try {redisTemplate.opsForList().rightPushAll(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存** param key 键* param value 值* param time 时间(秒)* return*/public boolean lSet(String key, ListObject value, long time) {try {redisTemplate.opsForList().rightPushAll(key, value);if (time 0) expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据索引修改list中的某条数据** param key 键* param index 索引* param value 值* return*/public boolean lUpdateIndex(String key, long index, Object value) {try {redisTemplate.opsForList().set(key, index, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 移除N个值为value** param key 键* param count 移除多少个* param value 值* return 移除的个数*/public long lRemove(String key, long count, Object value) {try {Long remove redisTemplate.opsForList().remove(key, count, value);return remove;} catch (Exception e) {e.printStackTrace();return 0;}}}
【5】最后的测试代码为
package com.black.util;
import com.black.pojo.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import javax.annotation.Resource;SpringBootTest(webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ZTest {Resourceprivate RedisUtil redisUtil;Testpublic void one() throws Exception {User user new User();user.setName(张三);user.setNick(我的风格独自秀);redisUtil.set(user2, user);System.out.println(redisUtil.get(user2));}
}
OK全部完成**************************************************************************************************************************************************************
27、Redis配置文件
【1】Redis.conf
units are case insensitive so 1GB 1Gb 1gB are all the same.
对大小写不敏感
*****************************
include /path/to/local.conf
include /path/to/other.conf
可以包含其他配置文件nginx也是这样)
*****************************
loadmodule /path/to/my_module.so
可以加载别的so库文件
*****************************
NETWORK网络
protected-mode xxx保护模式
port 6379 端口
daemonize yes 是否后台运行
pidfile /var/run/redis_6379.pid 如果以后台方式运行就需要指定一个pid进程文件
loglevel notice 默认就是notice生产环境
logfile 日志的文件位置名字
databases 16 数据库数量默认16个
*****************************
SNAPSHOTTING 快照
规定的时间内操作了多少才会触发持久化
save 900 1 如果900秒内至少有1个key修改则进行持久化操作
save 300 10 如果300秒内有10个key操作过则进行持久化
save 60 10000 如果60秒内操作了1万次则进行持久化
*****************************
stop-writes-on-bgsave-error yes 如果持久化出错是否继续工作
rdbcompression yes 是否压缩rdb文件需要消耗一些CPU资源
rdbchecksum yes 保存rdb文件是否进行错误检查校验
*****************************
REPLICATION 主从复制的
*****************************
SECURITY 安全可以设置密码
requirepass s19911009! 在这里进行实际设置。
config get requirepass
config set requirepass xxx
auth xxx
*****************************
CLIENTS 客户端限制
*****************************
MEMORY MANAGEMENT 内存管理
六大配置策略
*****************************
APPEND ONLY MODE aof模式默认是使用rdb的
appendonly yes
appendfilename appendonly.aof持久化文件名字
appendfilename appendonly.rdb
appendfsync everysec 每秒执行一次**************************************************************************************************************************************************************
28、持久化RDB
【1】Redis DataBase RDB
因为Redis是存在内存中所以一定需要持久化
是有个子进程专门负责这部分工作不影响主进程性能
【2】可以修改reids.conf
save 60 5 这是60秒修改5次可以触发快照
ps -ef|grep redis
flushall是默认生成rdb文件的
*****************************
所以save 60 5 或 flushall 或退出redis 都会产生rdb文件
备份会自动生成dump.rdb文件
*****************************
如果恢复rdb文件只需要放到redis启动目录下即可redis会自动检查恢复
【3】优缺点
优点
适合大规模数据恢复
对数据的完整性要求不高
*****************************
缺点
需要一定的时间间隔如果reids以外宕机最后一次修改的数据丢失
fork进程的时候会占用一定的内容空间**************************************************************************************************************************************************************
29、持久化AOF
【1】将我们的所有的命令记录下来类似history命令
appendonly yes 默认是不开启的需要手动配置
appendonly.aof就是对命令的记录这样就能通过命令回复数据牛批
cd /opt/redis/redis-6.0.6
我启动的默认是这个目录下的
【2】优缺点
优点
每次修改都同步文件的完整性更佳
每秒同步一次可能会丢失1秒的数据
从不同步效率是最高的
缺点
相对数据文件来说aof远远大于rdb修复速度比rdb慢
aof运行效率比rdb慢所以redis默认的是rdb而不是aof
【3】在主从复制中rdb就是备用的在从机上面
【4】扩展
rdb对数据进行快照存储
aof持久化存储每次记录对服务器写的操作
只做缓存如果只希望在服务器运行的时候存在不需要做持久化
同事开启两个持久化性能消耗会大点
rdb建议15分钟备份一次 save 900 1
aof 2秒写一次**************************************************************************************************************************************************************
30、Redis订阅发布
【1】pub/sub是一种消息通信模式
发送者publisher发送消息
订阅者sub接受消息
微信、微博、关注系统等
******************************************
第一个消息发送者
第二个频道channel
第三个消息订阅者
【2】相关命令
PUBSCREIBE xxx
SUBSCREIBE xxx
PUBLISH xxx
和微信公众号发送文章有人接收一样
可以实现即时聊天、群聊功能
【3】功能能用于的系统
实时消息系统
实时聊天
订阅、关注系统
稍微复杂的场景我们会使用消息中间件RMQ**************************************************************************************************************************************************************
31、Redis集群
【1】主从复制
Master
Slave1
Slave2
【2】数据的复制都是单向的读写分离
主机负责写从机负责读可以减轻服务器压力
【3】单台Redis最大使用内存不应该超过20G否则应该立刻使用集群
【4】环境配置只配置从库不用配置主库
info replication查看当前库的信息
# Replication
role:master
connected_slaves:0
master_replid:e084b9df28e88fb235b452a195920eba5a95266c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
【5】拷贝多个配置文件
cp redis.conf redis63791.conf
cp redis.conf redis63792.conf
cp redis.conf redis63793.conf
***********************************
修改的地方
port 63791
pidfile /var/run/redis_63791.pid
logfile 63791.log
dbfilename dump63791.rdb
***********************************
port 63792
pidfile /var/run/redis_63792.pid
logfile 63792.log
dbfilename dump63792.rdb
***********************************
port 63793
pidfile /var/run/redis_63793.pid
logfile 63793.log
dbfilename dump63793.rdb
【6】修改信息总结
端口号
pid名字
日志文件名字
dump.rdb名字
【7】依次启动可以开到三个服务都启动了
redis-server redis63791.conf
ls
redis-server redis63792.conf
ls
redis-server redis63793.conf
ls
*************************************
root 9846 1 0 16:01 ? 00:00:00 redis-server 0.0.0.0:6379
root 16531 1 0 16:16 ? 00:00:00 redis-server 0.0.0.0:63791
root 16934 1 0 16:17 ? 00:00:00 redis-server 0.0.0.0:63792
root 16965 1 0 16:17 ? 00:00:00 redis-server 0.0.0.0:63793
root 17109 3317 0 16:18 pts/0 00:00:00 grep --colorauto redis**************************************************************************************************************************************************************
32、主从复制
【1】配置一主二从
1是主 2 3是从
SLAVEOF 192.168.100.205 63791找谁当自己的老大
info replication 再次查看就变成从机了
【2】主机就能看到从机的信息
info replication
# Replication
role:master
connected_slaves:2
slave0:ip192.168.100.205,port63792,stateonline,offset84,lag1 从机1
slave1:ip192.168.100.205,port63793,stateonline,offset84,lag0 从机2
master_replid:844773fa614927f6cc88661e76379223be1f89d8
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:84
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:84
【3】真实的应该修改配置文件命令配置是临时的
redis.conf中操作配置
################################# REPLICATION
# replicaof masterip masterport
# masterauth master-password 如果主机有密码还需要配置密码
【4】细节知识主机负责写从机负责读
主机中所有的数据都会自动被从机保存
set k2 v2 从机不能写
READONLY You cant write against a read only replica.
【5】如果主机断开了
这时候配置还是在的。如果主机又来了则关系会自动恢复
【6】如果从机断开了命令行配置的主从
如果从机又回来了...从机默认就变成了主机了emmm
如果手动让它变成从机则它就能拿到主机的数据了。
说明只要变成了从机就会立刻同步数据。
【7】复制原理全量复制、增量复制。
slave启动成功连接到master会发送一个sync同步命令
master将整个数据同步到salve并完成一次完全同步。
master后续将继续桨新手机的修改命令依次传给slave完成同步。
只要是重新连接全量复制就会被执行一次**************************************************************************************************************************************************************
33、宕机后手动配置主机
【1】一主二从模式
【2】M63791-SM63792-S63793
63792用info replication查看角色是从节点
层层链路模式
【3】如果M63791宕机了
SM63792执行SLAVEOF no one 手动执行这个命令就自动成为master
如果M63791回来了就要重新配置了**************************************************************************************************************************************************************
34、哨兵模式
【1】这才是重点
【2】就是选主的自动版
哨兵哨兵也可能有多个多哨兵模式
63791
63792
63793
哨兵之间投票决定谁是主
【3】配置哨兵
vim mysentinel.conf
# 下年是配置的内容
sentinel monitor myredis 192.168.100.205 63791 1代表主机宕机slave投票
***********************************************
启动哨兵
redis-sentinel mysentinel.conf
***********************************************
如果master节点断开就会从从机中随机选择一个作为主随机63793被选中了
info replication
# Replication
role:master
connected_slaves:1
slave0:ip192.168.100.205,port63792,stateonline,offset14302,lag0
master_replid:4aaf00f57e7d45b77a03453e6e63480ae2ec6c44
master_replid2:844773fa614927f6cc88661e76379223be1f89d8
master_repl_offset:14447
second_repl_offset:13396
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:43
repl_backlog_histlen:14405***********************************************
如果主机再回来主机就自动成为从机了
【4】优缺点
优点
哨兵集群基于主从复制模式所有的主从配置有点全部拥有
主从可以切换故障可以转移系统的可用性就回更好
哨兵模式就是主从模式的升级手动到自动更加健壮、
***********************************************
缺点
Redis不好在线扩容集群容量一旦达到上限在线扩容就十分麻烦
实现哨兵模式的配置其实是很麻烦的里面会有很多选择
如果有哨兵集群还需要配置多个哨兵端口**************************************************************************************************************************************************************
35、缓存穿透和雪崩
【1】面试高频工作常用
读的请求先去缓存中查询如果没有去查询数据库
【2】穿透查不到
如果redis内存没有去数据库查询如果是秒杀同一时间大量请求去查询mysql直接就奔了
两种方式第一种加个过滤器第二种缓存null对象
【3】缓存击穿量太大缓存过期
某一个热点不停地扛着大并发
当这个key在失效的瞬间持续的大并发就穿破缓存查询到数据库
加互斥锁保证只有一个线程进去其余的进行等待
【4】雪崩
缓存集中过期或者redis宕机
双十一会停掉一些服务保证主要的服务可用
解决方案
reids集群
限流降级
数据预热**************************************************************************************************************************************************************
36、小结与拓展
【1】reids概述
【2】安装
【3】实战场景
【4】与JAVA结合Jedis SpringBoot结合
【5】redis配置持久化
【6】发布订阅
【7】主从复制
【8】redis集群、哨兵模式
【9】缓存场景问题与解决方案