大佬教程收集整理的这篇文章主要介绍了什么!Redis不会用!看完这个你就是Redis大牛了!,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
联系作者:扣扣 190557020
什么是nosql:
NoSQLc;指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写c;是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式c;无需多余操作就可以横向扩展。
常用的NoSQL数据库c;redis,MongoDB,Es,
大致分为以下几种:
键值数据库
列组数据库
文档数据库
图形数据库
直接下载直接解压即可用
下载地址:链接: https://pan.baidu.com/s/1chv4tPBCI6tV3HHIb-92Tw 提取码: g9n3
配置一个快速启动的脚本
创建redis-start.bat文件c;右击编辑c;输入 redis-server redis.windows.conf 保存即可
双击启动
默认端口为6379
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LctcMVXJ-1627702088495)(H:技术点redisredis-这一篇就够了.assets1627566370994.png)]
redis-cli.exe 文件是命令行操作c;输入keys * 查看所有键
出现以上界面c;windows下的redis就算安装完成了c;
路灯
https://www.cnblogs.com/xsge/p/13841875.html
记得关闭防火墙/开放端口
centos7 下的 docker安装redis
#启动docker
systemctl start docker
#查找redis的镜像
docker search redis
# 下载指定版本c;c;
docker pull redis:6.0-rc
此处需要联网
#查看docker里的镜像
docker images
#创建挂载目录c;配置文件需要将下载一份配置上去c;redis.conf,
@H_662_115@mkdir -p /home/redis/myredis
#conf文件的目录
//创建data
cd /home/redis/myredis
@H_662_115@mkdir data
redis各版本配置文件下载:https://redis.io/topics/config
安装的命令
docker run -p 6379:6379
--name niuzi_redis -v /home/redis/myredis/myredis.conf:/etc/redis/redis.conf
-v /home/redis/myredis/data:/data -d redis redis-server /etc/redis/redis.conf
--appendonly yes
redis:6.0-rc
#二选一c;下面这个使用的默认的配置
docker run -itd --name redis6 -p 6379:6379 redis:6.0-rc
–restart=always 总是开机启动
-p 6379:6379 将6379端口挂载出去
–name 给这个镜像取一个名字
-v 数据卷挂载
/home/redis/myredis/myredis.conf:/etc/redis/redis.conf
这里是将 liunx 路径下的myredis.conf 和redis下的redis.conf 挂载在一起。 /home/redis/myredis/data:/data 这个同上
redis-server /etc/redis/redis.conf 以配置文件启动redisc;加载容器内的conf文件c;最终找到的是挂载的目录 /etc/redis/redis.conf 也就是liunx下的/home/redis/myredis/myredis.conf
–appendonly yes 开启redis 持久化
#查看是否安装成功
docker ps -a
#运行redis
docker start niuzi_redis #可以是名称c;也可以是最前面的id
#打开redis命令测试
docker exec -it redis6-two redis-cli
#输入测试命令
keys *
出现以下界面则表示安装成功
端口号默认是6379
一共有16个数据库c;
redis是单线程
redis可以进行持久化操作
单线程+多路io复用
原子性 所谓原子操作是指不会被线程调度机制打断的操作
这种操作一旦开始c;就一直运行到结束c;中间不会有任何 context switch (切换到另一个线程)。
(1)在单线程中c; 能够在单条指令中完成的操作都可以认为是"原子操作"c;因为中断只能发生于指令之间。
(2)在多线程中c;不能被其它进程(线程)打断的操作就叫原子操作。
#查看所有key
keys *
#判断该key是否存在 返回1则存在c;0则不存在
exists key
#查看key是什么类型
type key
#删除key
del key
#根据value选择非阻塞删除
unlink key
#设置key的过期时间,10描
expire key 10
#查看还有多少秒过期 -1永不过期,-2表示已过期
ttl key
#切换数据库
SELEct 0/1/2/3/....
#查看当前数据库有多少数量的key
dbsize
!!!!!!慎用!!!!!
#清空当前库
flushdb
#通杀全部库
flushall
String类型是二进制安全的c;意味着他可以保存任何数据c;比如序列化
一个redis中字符串value最多可以是512M
#存入值c;重复往key中存储会覆盖值
set key value
#获取值
get key
#追加值
append key value
#获取长度
strlen
#当key不存在的时候设置key的值
setnx key value
单键多值
redis 列表是简单的字符串列表c;按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
它的底层实际是个双向链表c;对两端的操作性能很高c;通过索引下标的操作中间的节点性能会较差
#从表头添加或表尾
lpush/rpush key value,key value
#从表头或表尾吐出一个值c;
lpop/rpop key #键在则在c;键光则亡
#根据下标范围获取值 多用于 0 -1 获取全部
lrange key start stop
#在<value>的后面插入<newvalue>插入值
linsert <key> before <value><newvalue>
#从左边删除n个value(从左到右)
lrem <key><n><value>
#将列表key下标为index的值替换成value
lset<key><index><value>
set对外提供的功能与list类似是一个列表的功能c;特殊之处在于set是可以自动排重的c;当你需要存储一个列表数据c;又不希望出现重复数据时c;set是一个很好的选择c;并且set提供了判断某个成员是否在一个set集合内的重要接口c;这个也是list所不能提供的。
#将一个或多个 member 元素加入到集合 key 中c;已经存在的 member 元素将被忽略
sadd <key><value1><value2> .....
#取出该集合的所有值
smembers <key>
#判断集合<key>是否为含有该<value>值c;有1c;没有0
sismember <key><value>
#返回该集合的元素个数。
scard<key>
#删除集合中的某个元素。
srem <key><value1><value2> ....
#随机从该集合中吐出一个值。
spop <key>
#随机从该集合中取出n个值。不会从集合中删除 。
srandmember <key><n>
#返回两个集合的交集元素。
sinter <key1><key2>
#返回两个集合的并集元素。
sunion <key1><key2>
#返回两个集合的差集元素(key1中的c;不包含key2中的)
sdiff <key1><key2>
Java中HashSet的内部实现使用的是HashMapc;只不过所有的value都指向同一个对象。redis的set结构也是一样c;它的内部也使用hash结构c;所有的value都指向同一个内部值
redis hash 是一个键值对集合。
redis hash是一个String类型的field和value的映射表c;hash特别适合用于存储对象。
用户ID为查找的keyc;存储的value用户对象包含姓名c;年龄c;生日等信息c;
#给<key>集合中的 <field>键赋值<value>
hset <key><field><value>
#从<key1>集合<field>取出 value
hget <key1><field>
#批量设置hash的值
hmset <key1><field1><value1><field2><value2>...
#查看哈希表 key 中c;给定域 field 是否存在。
hexists<key1><field>
#列出该hash集合的所有field
hkeys <key>
#列出该hash集合的所有value
hvals <key>
Hash类型对应的数据结构是两种:ziplist(压缩列表)c;hashtable(哈希表)。当field-value长度较短且个数较少时c;使用ziplistc;否则使用hashtable。
redis有序集合zset与普通集合set非常相似c;是一个没有重复元素的字符串集合。
不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的c;但是评分可以是重复了 。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。
访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
多用于c;点赞之类的
#将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
zadd <key><score1><value1><score2><value2>…
#返回有序集 key 中c;下标在<start><stop>之间的元素
#带WITHSCORESc;可以让分数一起和值返回到结果集。
zrange <key><start><stop> [WITHSCORES]
#返回有序集 key 中c;所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
zrangebyscore key minmax [withscores] [limit offset count]
#同上c;改为从大到小排列。
zrevrangebyscore key maxmin [withscores] [limit offset count]
#为元素的score加上增量
zincrby <key><increment><value>
#删除该集合下c;指定值的元素
zrem <key><value>
#统计该集合c;分数区间内的元素个数
zcount <key><@H_649_91@min><@H_649_91@max>
#返回该值在集合中的排名c;从0开始
zrank <key><value>
SortedSet(zset)是redis提供的一个非常特别的数据结构c;一方面它等价于Java的数据结构Map<String, Double>c;可以给每一个元素value赋予一个权重scorec;另一方面它又类似于TreeSetc;内部的元素会按照权重score进行排序c;可以得到每个元素的名次c;还可以通过score的范围来获取元素的列表
zset底层使用了两个数据结构
(1)hashc;hash的作用就是关联元素value和权重scorec;保障元素value的唯一性c;可以通过元素value找到相应的score值。
(2)跳跃表c;跳跃表的目的在于给元素value排序c;根据score的范围获取元素列表。
进行位操作c;
合理地使用操作位能够有效地提高内存使用率和开发效率。
(1) Bitmaps本身不是一种数据类型c; 实际上它就是字符串(key-value) c; 但是它可以对字符串的位进行操作。
(2) Bitmaps单独提供了一套命令c; 所以在redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组c; 数组的每个单元只能存储0和1c; 数组的下标在Bitmaps中叫做偏移量。
#添加数据-设置Bitmaps中某个偏移量的值(0或1)
setbit key <key><offset><value>
#获取偏移量
get <key><offset>
统计**字符串**被设置为1的bit数。一般情况下c;给定的整个字符串都会被进行计数c;通过指定额外的 start 或 end 参数c;可以让计数只在特定的位上进行。start 和 end 参数的设置c;都可以使用负数值:比如 -1 表示最后一个位c;而 -2 表示倒数第二个位c;start、end 是指bit组的字节的下标数c;二者皆包含
bitcount<key>[start end] #统计字符串从start字节到end字节比特值为1的数量
start和end代表起始和结束字节数
bitop是一个复合操作c; 它可以做多个Bitmaps的and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在destkey中。
bitop and(or/not/xor) <destkey> [key…]
与set对比
当网站用户访问量大的时候可以使用bitmapsc;可以节省内存
当网站访问量较小的时候是不如set的
基数统计的算法
在工作当中c;我们经常会遇到与统计相关的功能需求c;比如统计网站PV(PageView页面访问量),可以使用redis的incr、incrby轻松实现。
但像UV(UniqueVisitorc;独立访客)、独立IP数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。
解决基数问题有很多种方案:
(1)数据存储在MySQL表中c;使用disTinct count计算不重复个数
(2)使用redis提供的hash、set、bitmaps等数据结构来处理
以上的方案结果精确c;但随着数据不断增加c;导致占用空间越来越大c;对于非常大的数据集是不切实际的。
能否能够降低一定的精度来平衡存储空间?redis推出了HyperLogLog
redis HyperLogLog 是用来做基数统计的算法c;HyperLogLog 的优点是c;在输入元素的数量或者体积非常非常大时c;计算基数所需的空间总是固定的、并且是很小的。
在 redis 里面c;每个 HyperLogLog 键只需要花费 12 KB 内存c;就可以计算接近 2^64 个不同元素的基数。这和计算基数时c;元素越多耗费内存就越多的集合形成鲜明对比。
但是c;因为 HyperLogLog 只会根据输入元素来计算基数c;而不会储存输入元素本身c;所以 HyperLogLog 不能像集合那样c;返回输入的各个元素。
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8}c; 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内c;快速计算基数。
#添加指定元素到 HyperLogLog 中
pfadd <key>< element> [element ...]
#将所有元素添加到指定HyperLogLog数据结构中。如果执行命令后HLL估计的近似基数发生变化c;则返回1c;否则返回0。
#统计数量
pfcount <key>
#pfmerge 将一个或多个HLL合并后的结果存储在另一个HLL中
#将k1 k2的值合并放在k3中
pfmerge k3 k1 k2
redis 3.2 中增加了对GEO类型的支持。GEOc;Geographicc;地理信息的缩写。该类型c;就是元素的2维坐标c;在地图上就是经纬度。redis基于该类型c;提供了经纬度设置c;查询c;范围查询c;距离查询c;经纬度Hash等常见操作。
geoadd<key>< longitude><latitude><@H_649_91@member> [longitude latitude member...]
#实例
geoadd china:city 121.47 31.23 shanghai
geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing
两极无法直接添加c;一般会下载城市数据c;直接通过 Java 程序一次性导入。
有效的经度从 -180 度到 180 度。有效的纬度从 -85.05112878 度到 85.05112878 度。
当坐标位置超出指定范围时c;该命令将会返回一个错误。
已经添加的数据c;是无法再次往里面添加的。
南极与北极不可添加
geopos <key><@H_649_91@member> [@H_649_91@member...] #获得指定地区的坐标值
#获取两个地区的直线距离是多少
geodist <key><@H_649_91@member1><@H_649_91@member2> [@H_649_91@m|km|ft|@H_649_91@mi ]
单位:
@H_4_13@m 表示单位为米[默认值]。km 表示单位为千米。
@H_4_13@mi 表示单位为英里。ft 表示单位为英尺。
如果用户没有显式地指定单位参数c; 那么 GEODIST 默认使用米作为单位
#以给定的经纬度为中心c;找出某一半径内的元素
georadius <key>< longitude><latitude>radius m|km|ft|@H_649_91@mi
什么是发布和订阅
redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息c;订阅者 (sub) 接收消息。
redis 客户端可以订阅任意数量的频道
当给这个频道发布消息后c;消息就会发送给订阅的客户端
命令行实现
打开2个客户端c;
1、 打开一个客户端订阅chAnnel1
SUBSCRIBE chAnnel1
2丶打开另一个客户端c;给chAnnel1发布消息Hello
打开第一个客户端可以看到发送的消息c;发布的消息没有持久化c;如果在订阅的客户端收不到Helloc;只能收到订阅后发布的消息
在开发与练习中c;频繁的使用命令是不可行的c;为了提升开发效率c;更直观的将数据展示出来c;需要安装一个redis的可视化
软件安装 redisDesktopManager
链接:https://pan.baidu.com/s/14rpZn6ZEEfpSWT5bOJjeYg 提取码:t16i
傻瓜式安装–一直下一步c;安装链接根据个人修改
启动软件
创建redis链接
显示成功链接后点击ok
可以直观的看到c;我们有16个数据库。每个数据库存放了什么c;值是什么
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
redis:
# redis数据库索引(默认为0)c;我们使用索引为3的数据库c;避免和其他数据库冲突
database: 3
# redis服务器地址(默认为loaclhost)
host: 192.168.73.12
# redis端口(默认为6379)
port: 6379
# redis访问密码(默认为空)
password: pwd123
# redis连接超时时间(单位毫秒)
timeout: 0
# redis连接池配置
pool:
# 最大可用连接数(默认为8c;负数表示无限)
@H_792_1415@max-active: 8
# 最大空闲连接数(默认为8c;负数表示无限)
@H_792_1415@max-idle: 8
# 最小空闲连接数(默认为0c;该值只有为正数才有用)
@H_792_1415@min-idle: 0
# 从连接池中获取连接最大等待时间(默认为-1c;单位为毫秒c;负数表示无限)
@H_792_1415@max-wait: -1
这里我们使用的最终yml为
redis: #redis其他的都使用默认配置c;也可以不配c;全部使用默认配置c;这里为了直观的学习固修改host和port
host: 127.0.0.1 #/localhost
# redis端口(默认为6379)
port: 6379
server:
port: 9001 #端口号
spring:
application:
name: spring-boot-redis-0730 #项目名称
@resource
private StringredisTemplate StringredisTemplate;
// @resource 在此工程中使用Stringredistemplate
// private redisTemplate redisTemplate;
StringredisTemplate 与 redisTemplate 的区别
resource 与 Autowried的区别
//存入redis
@Test
void addStringredis() {
ValueOperations<String, String> Stringredis
= StringredisTemplate.opsForValue();
Stringredis.set("job","male");
Stringredis.set("jack","male");
Stringredis.set("lisa","female");
Stringredis.set("alili","female");
}
/**
* @description 根据key获取值
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 12:18
*/
@Test
void getStringredis(){
ValueOperations<String, String> Stringredis = StringredisTemplate.opsForValue();
//根据key获取值
String job = Stringredis.get("job");
System.out.println("job = " + job);
}
//job = male
/**
* @description 给key设置过期时间c;使用timeunit函数
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 12:23
*/
@Test
void setExpireredis(){
StringredisTemplate.opsForValue().set("job","male",30,TimeUnit.SECONDS);
}
/**
* @description 对list进行左右插入操作
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 14:43
*/
@Test
void setredisList(){
// 在变量左边添加元素值。右边同理c;只是方法名换成rightPush
// StringredisTemplate.opsForList().rightPush()
//批量添加时c;直接在后面拼接c;例如
// StringredisTemplate.opsForList().leftPush("list","a","b","c");
//也可以直接将集合放进去
// StringredisTemplate.opsForList().leftPush("list",List对象);
StringredisTemplate.opsForList().leftPush("list","a");
StringredisTemplate.opsForList().leftPush("list","b");
StringredisTemplate.opsForList().leftPush("list","c");
}
/**
* @description Ipuest
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 14:50
*/
@Test
void Ipuest(){
// 如果存在集合则添加元素。
StringredisTemplate.opsForList().leftPushIfPresent("presentList","o");
List<String> list = StringredisTemplate.opsForList().range("presentList", 0, -1);
System.out.println("通过leftPushIfPresent(K key, V value)方法向已存在的集合添加元素:" + list);
}
// size(K key)
//获取集合长度。
long listLength = redisTemplate.opsForList().size("list");
System.out.println("通过size(K key)方法获取集合list的长度为:" + listLength);
// 16、rightPop(K key)
// 移除集合中右边的元素。
// rightPop(K key, long timeout, TimeUnit unit)
// 移除集合中右边的元素在等待的时间里c;如果超过等待的时间仍没有元素则退出
String list = StringredisTemplate.opsForList().rightPop("list");
System.out.print("通过rightPop(K key)方法移除的元素是:" + list);
List<String> list1 = StringredisTemplate.opsForList().range("list", 0, -1);
System.out.println(",剩余的元素是:" + list1);
/**
* @description 获取全部的数据
* @params []
* @return void
* @author -还怕大雨吗
* @date 2021/7/30 14:46
*/
@Test
void getredisList(){
List<String> list = StringredisTemplate.opsForList().range("list", 0, -1);
System.out.println("全部的list = " + list);
List<String> flist = StringredisTemplate.opsForList().range("list", 1, 2);
System.out.println("范围取值的flist = " + flist);
}
//全部的list = [c, b, a]
//范围取值的flist = [b, a]
参码宗路灯
https://www.shenmazong.com/album/1402622833635569664/1
使用springboot+redis 完成短信发送c;验证短信是否超时
这里的短信验证今后也可以在项目中使用
–导入依赖
<!-- 短信接口依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>9.3.7.v20160115</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
导入工具类c;AuthCodeUtil+httpUtils
第一个是生成验证码c;第二个是发送短信
链接:https://pan.baidu.com/s/1-6a0F11FkDslVdke7PvPyw 提取码:dayy
controller类
@RestController
public class CodeController {
@resource
private StringredisTemplate StringredisTemplate;
@PostMapping("sendCode")
public Object sendCode(String mobile){
try {
//生成规则c; 0-9/a-z/A-z 直接输入即可
String code = AuthCodeUtil.getCode("0-9a-z", 8);
AuthCodeUtil.sendMsgToPhone(code,@H_649_91@mobile);
System.out.println("mobile = " + mobile);
StringredisTemplate.opsForValue().set(@H_649_91@mobile,code,1, TimeUnit.minutES);
return "发送成功,验证码为"+code;
} catch (Exception e) {
e.printStackTrace();
}
return "发送失败";
}
@PostMapping("pushCode")
public Object pushCode(String code,String mobile){
if(@H_649_91@mobile!=null){
String redisCode = StringredisTemplate.opsForValue().get(@H_649_91@mobile);
System.out.println("redisCode = " + redisCode);
if (redisCode.equals(code)){
return "登陆成功";
}
return "登陆失败";
}
return "登陆失败";
}
//mobile = 18434290135
//redisCode = u8ofwhni
//过1分钟后登陆c;则登陆失败
//因为无法获取到redis存放的手机号
在执行redis执行指令过程中c;多条连续执行的指令被干扰c;打断c;插队
redis事务一个命令执行的队列c;将一系列预定义命令包装成一个整体(一个队列)c;当执行的时候c;一次性按照添加顺序执行c;中间不会被打断或者干扰
开启事务。multi
设定事务的开启位置c;此指令执行之后c;后续的所有指令均加入事务中
执行事务。exec
设定事务的关闭位置c;同时执行事务c;与multi成对出现c;成对使用
取消事务。discard
终止当前事务的定义c;发生在开启和提交之间
加入事务的命令暂时进入到任务队列中c;并没有立即执行c;只有执行exec命令才开始执行
执行的顺序是队列执行
根据输入的命令来判断该如何执行
在事务中出现语法错误的时候c;整体事务所有的命令都不会执行c;包括正确的语法
如果语法是正确的c;但是操作是错误的c;比如让list去执行set的方法c;是会分开执行的
已经执行完毕的命令对应的数据是不会自动回滚的c;需要程序员自己在代码中实现回滚
顾名思义c;就是很乐观c;每次去拿数据的时候都认为别人不会修改c;所以不会上锁c;但是在更新的时候会判断一下在此期间别人有没有去更新这个数据c;可以使用版本号等机制。乐观锁适用于多读的应用类型c;这样可以提高吞吐量。redis就是利用这种check-and-set机制实现事务的c;用的比较多c;比如抢票c;
顾名思义c;就是很悲观c;每次去拿数据的时候都认为别人会修改c;所以每次在拿数据的时候都会上锁c;这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制c;比如行锁c;表锁等c;读锁c;写锁等c;都是在做操作之前先上锁。效率偏低c;在互联网大并发下不建议使用
单独的隔离操作
事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中c;不会被其他客户端发送来的命令请求所打断。
没有隔离级别的概念
队列中的命令没有提交之前都不会实际被执行c;因为事务提交前任何指令都不会被实际执行
不保证原子性
事务中如果有一条命令执行失败c;其后的命令仍然会被执行c;没有回滚
redis是内存数据库c;如果不进行持久化c;一旦服务器退出c;服务器中的数据库状态也会消失c;所以redis实现了持久化
是什么:
在指定的时间间隔内将内存中的数据集快照写入磁盘c; 也就是行话讲的Snapshot快照c;它恢复时是将快照文件直接读到内存里
redis会单独创建(fork)一个子进程来进行持久化c;会先将数据写入到 一个临时文件中c;待持久化过程都结束了c;再用这个临时文件替换上次持久化好的文件。 整个过程中c;主进程是不进行任何IO操作的c;这就确保了极高的性能 如果需要进行大规模数据的恢复c;且对于数据恢复的完整性不是非常敏感c;那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
在redis.conf中配置文件名称c;默认为dump.rdb
save 30 10 #在30s内进行了10次操作,同样的意思
触发条件
不管触发以上三个save条件的哪一个c;都会进行持久化
执行flushall命令c;也会产生dump.rdb文件c;但里面是空的c;无意义
退出redis也是产生rdb文件
备份自动生成一个rdb文件
恢复rdb文件
将rdb文件放在redis启动目录就可以c;redis启动的时候会自动检查dump.rdb恢复其中的数据
config get dir
#/user/local/bin #如果存在就会自动触发
几乎默认的数据就可以供我们使用了
优点:
适合大规模的数据恢复 对数据完整性和一致性要求不高更适合使用 节省磁盘空间 恢复速度快
缺点:
在备份周期在一定间隔时间做一次备份c;所以如果redis意外down掉的话c;就会丢失最后一次快照后的所有修改
Fork的时候c;内存中的数据被克隆了一份c;大致2倍的膨胀性需要考虑,会占用一定的内存空间
虽然redis在fork时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能
aof是什么
以日志的形式来记录每个写操作(增量保存)c;将redis执行过的所有写指令记录下来(读操作不记录)c; 只许追加文件但不可以改写文件c;redis启动之初会读取该文件重新构建数据c;换言之c;redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
AOF保存的是appendonly.aof 文件
持久化流程:
客户端的请求写命令会被append追加到AOF缓冲区内; AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中; AOF文件大小超过重写策略或手动重写时c;会对AOF文件rewrite重写c;压缩AOF文件容量; redis服务重启时c;会重新load加载AOF文件中的写操作达到数据恢复的目的;
@H_696_3246@
AOF默认是不开启的需要在配置文件中手动打开
可以在redis.conf中配置文件名称c;默认为 appendonly.aof
AOF文件的保存路径c;同RDB的路径一致。
AOF和RDB同时开启c;系统默认取AOF的数据(数据不会存在丢失)
AOF启动/修复/恢复
AOF的备份机制和性能虽然和RDB不同, 但是备份和恢复的操作同RDB一样c;都是拷贝备份文件c;需要恢复时再拷贝到redis工作目录下c;启动系统即加载。
正常恢复
修改默认的appendonly noc;改为yes 将有数据的aof文件复制一份保存到对应目录(查看目录:config get dir) 恢复:重启redis然后重新加载
异常恢复
修改默认的appendonly noc;改为yes
如果这个aof文件错位。redis是启动不起来的c;需要修复这个aof文件c;如遇到AOF文件损坏c;通过/usr/local/bin/redis-check-aof–fix appendonly.aof进行恢复 备份被写坏的AOF文件 恢复:重启redisc;然后重新加载
优点和缺点
优点:
1、每一次修改都同步c;文件的完整会更加好
2、每秒同步一次c;可能会丢失一秒的数据
3、从不同步c;效率最高
缺点:
1、相对于数据文件来说c;aof远远大于rdb 修复的速度也比rdb慢很多
2、aof运行效率也要比rdb慢c;所以redis默认的配置是rdb持久化
重写规则
aof默认就是文件的无限追加。文件只会越来越大
如果aof文件大于64mc;太大了c;fork一个新的进程来进行文件的重写
如何选择哪种持久化方式
一般来说c; 如果想达到足以媲美 POSTGReSQL 的数据安全性c; 你应该同时使用两种持久化功能。
如果你非常关心你的数据c; 但仍然可以承受数分钟以内的数据丢失c; 那么你可以只使用 RDB 持久化。
有很多用户都只使用 AOF 持久化c; 但并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份c; 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快。
官方推荐两个都启用。
如果只是做纯内存缓存c;可以都不用。
性能与实践
我们都知道RDB的快照、AOF的重写都需要forkc;这是一个重量级操作c;会对redis造成阻塞。因此为了不影响redis主进程响应c;我们需要尽可能降低阻塞。
降低fork的频率c;比如可以手动来触发RDB生成快照、与AOF重写; 控制redis最大使用内存c;防止fork耗时过长; 使用更牛逼的硬件; 合理配置Linux的内存分配策略c;避免因为物理内存不足导致fork失败。 在线上我们到底该怎么做?我提供一些自己的实践经验。
如果redis中的数据并不是特别敏感或者可以通过其它方式重写生成数据c;可以关闭持久化c;如果丢失数据可以通过其它途径补回; 自己制定策略定期检查redis的情况c;然后可以手动触发备份、重写数据; 单机如果部署多个实例c;要防止多个机器同时运行持久化、重写操作c;防止出现内存、CPU、IO资源竞争c;让持久化变为串行; 可以加入主从机器c;利用一台从机器进行备份处理c;其它机器正常响应客户端的命令; RDB持久化与AOF持久化可以同时存在c;配合使用。
因为RDB文件只用作后备用途c;建议只在Slave上持久化RDB文件c;而且只要15分钟备份一次就够了c;只保留save 900 1这条规则。
如果使用AOFc;好处是在最恶劣情况下也只会丢失不超过两秒数据c;启动脚本较简单只load自己的AOF文件就可以了。
代价,一是带来了持续的IOc;二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。
只要硬盘许可c;应该尽量减少AOF rewrite的频率c;AOF重写的基础大小默认值64M太小了c;可以设到5G以上。
默认超过原大小100%大小时重写可以改到适当的数值。
主从复制-master/slave
主机数据更新后根据配置和策略c;自动同步到备机的master/slaver机制c;R_641_11845@aster以写为主c;slave以读为主
配置集群也都是多个一主多从
能干什么
读写分离
容灾恢复
怎么玩:
配置从(库)不配置主(库)
拜个大哥
从库配置:slaveof 主库 ip 主库端口
每次与master断开之后c;都需要重新连接c;除非配置进redis.conf文件c;否则就配进配置文件c;每次启动都读
修改配置文件细节操作
1、拷贝多个redis.conf文件
拷贝多个redis.conf文件include(写绝对路径) 拷贝配置文件
2、开启多个daemonize yes
3、pid文件名称 pidfile
4、指定端口
5、log文件名字
6、dump.rdp名字
7、Appendonly 关掉或者换名字
include /myredis/redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dumP6379.rdb
redis-server #配置名称 #启动redis
启动之后查看主从情况
info Replication
#打印主从复制的相关信息
redis -cli 6379/6380/6381 #启动多个redis客户端
配从不配主
slaveof <ip><port>
#将自己注册给主机
#slaveof 127.0.0.1 6379
#使用命令查看主机配置
info Replication
配置成功就是这个样子
在主机中使用写的命令c;从机中可以查询c;但是如果在从机写c;就会报错c;
一主二仆
当一个从服务器挂掉之后c;重启之后的状态是主服务器的状态c;需要重新注册到主服务器c;数据是从头开始复制c;相当于c;重新复制了一遍c;
当大哥挂了c;小弟不会上位c;小弟永远认这个大哥c;
薪火相传
大哥永远是大哥c;小弟也会有小弟c;小弟挂了下面的小弟就全挂了c;大哥无法跨级
反客为主
slaveof no one
原理:
1、当从链接上主服务器之后c;从服务器向主服务器发送进行数据同步消息
2、主服务器接到从服务器发送过来的同步消息c;把主服务器数据进行持久化c;rdb文件
把rdb文件发送从服务器c;从服务器拿到rdb进行读取
3、每次主服务器进行写操作之后c;和从服务器进行数据同步c;都是主服务器发起的c;相当于全量复制c;增量复制
是什么:
反客为主的自动版c;能够后台监控主机是否故障c;如果故障了根据投票数自动将从库转换为主库
怎么用:
自定义的/myredis目录下新建senTinel.conf文件c;名字绝不能错
senTinel monitor mymaster 127.0.0.1 6379 1
#其中mymaster为监控对象起的服务器名称c; 1 为至少有多少个哨兵同意迁移的数量
启动哨兵
/usr/local/bin
#redis做压测可以用自带的redis-benchmark工具
#执行redis-senTinel /myredis/senTinel.conf
当主机挂掉之后c;从机选举新的主机
(大概10秒左右可以看到哨兵窗口日志c;切换了新的主机)
哪个从机会被选举为主机呢?根据优先级别:slave-priority
原主机重启后会变为从机。
理解哨兵
新皇登基之后c;老皇帝会被拉下马c;不能作皇帝了c;变成从机
选举规则
优先级在redis.conf中默认:slave-priority 100c;值越小优先级越高
新版本的是:replica-priortity 100
偏移量是指获得原主机数据最全的
每个redis实例启动后都会随机生成一个40位的runi
复制延时
由于所有的写操作都是先在Master上操作c;然后同步更新到Slave上c;所以从Master同步到Slave机器有一定的延迟c;当系统很繁忙的时候c;延迟问题会更加严重c;Slave机器数量的增加也会使这个问题更加严重。
另外c;主从模式c;薪火相传模式c;主机宕机c;导致ip地址发生变化c;应用程序中配置需要修改对应的主机地址、端口等信息。
之前通过代理主机来解决c;但是redis3.0中提供了解决方案。就是无中心化集群配置。
代理主机
相当于有一个代理机器来访问c;需要的机器比较多
无中心化集群配置
redis 集群实现了对redis的水平扩容c;即启动N个redis节点c;将整个数据库分布存储在这N个节点中c;每个节点存储总数据的1/N。
redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯c; 集群也可以继续处理命令请求。
制作6个实例c;端口号不冲突就可
复制多个redisc;删除rdb文件c;使用最初始的配置文件c;
Appendonly 关掉或者换名字
配置修改
cluster-enabled yes #打开集群模式
cluster-config-file nodes-6379.conf #设定节点配置文件名
cluster-node-timeout 15000 #设定节点失联时间c;超过该时间(毫秒)c;集群自动进行主从切换。
修改别的配置文件c;:%s/6379/6380—以此类推
低版本需要装rb环境c;在6.1已经自动装好了c;然后才能进行集群操作
#进入安装环境
cd /opt/redis-6.2.1/src
#根据端口什么的自行修改
redis-cli --cluster create --cluster-replicas 1
192.168.11.101:6379 192.168.11.101:6380 192.168.11.101:6381 192.168.11.101:6389 192.168.11.101:6390 192.168.11.101:6391
询问是否接受这种分配
连接集群
-c #采用集群策略连接c;设置数据会自动切换到相应的写主机
#命令查看集群信息
cluster nodes
分配原则
分配原则尽量保证每个主数据库运行在不同的IP地址c;每个从库和主库不在一个IP地址上。保证集群的高可用c;主和主分开放c;从和主分开放c;
slots插槽
一个 redis 集群包含 16384 个插槽(hash slot)c; 数据库中的每个键都属于这 16384 个插槽的其中一个c;
取值范围为 0-16383
集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽c; 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
集群中的每个节点负责处理一部分插槽。 举个例子c; 如果一个集群可以有主节点c; 其中:
节点 A 负责处理 0 号至 5460 号插槽。
节点 B 负责处理 5461 号至 10922 号插槽。
节点 C 负责处理 10923 号至 16383 号插槽。
在集群存入值
你不能使用多个key value进行存储c;因为无法计算插槽
当你需要存入多个key value的时候c;可以使用分组的形式存储
自己只能查看自己插槽中的值
CLUSTER GETKEYSINSLOT <slot><count> #返回 count 个 slot 槽中的键。
当集群中某个主节点挂了之后c;从节点马上成为主节点c;当主节点恢复之后c;变成主节点
如果所有某一段插槽的主从节点都宕掉c;redis服务是否还能继续?
如果某一段插槽的主从都挂掉c;而cluster-require-full-coverage 为yes c;那么 c;整个集群都挂掉
如果某一段插槽的主从都挂掉c;而cluster-require-full-coverage 为no c;那么c;该插槽数据全都不能使用c;也无法存储。
redis.conf中的参数 cluster-require-full-coverage
优点:
实现扩容-分摊压力-无中心配置相对简单
缺点:
多键操作是不被支持的
多键的redis事务是不被支持的。lua脚本不被支持
由于集群方案出现较晚c;很多公司已经采用了其他的集群方案c;而代理或者客户端分片的方案想要迁移至redis clusterc;需要整体迁移而不是逐步过渡c;复杂度较大。
1、数据库压力变大c;应用访问变慢c;访问redis堆积过大c;导致全部崩溃
问题:
1、在极少时间段c;查询大量key的集中过期情况
解决方案:
(1)构建多级缓存架构:nginx缓存 + redis缓存 +其他缓存(ehcache等)
(2)使用锁或队列: 用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写c;从而避免失效时大量的并发请求落到底层存储系统上。不适用高并发情况
(3) 设置过期标志更新缓存:
记录缓存数据是否过期(设置提前量)c;如果过期会触发通知另外的线程在后台去更新实际key的缓存。
(4) 将缓存失效时间分散开:
比如我们可以在原有的失效时间基础上增加一个随机值c;比如1-5分钟随机c;这样每一个缓存的过期时间的重复率就会降低c;就很难引发集体失效的事件。
1、应用服务器压力变大
出现很多的非正常的url访问
多是出现黑客攻击c;恶意攻击
目的不是获取数据c;是让服务器崩溃
解决方案
1、对空值作缓存c;
如果一个查询返回的数据为空(不管是数据是否不存在)c;我们仍然把这个空结果(null)进行缓存c;设置空结果的过期时间会很短c;最长不超过五分钟
2、设置白名单
使用bitmaps类型定义一个可以访问的名单c;名单id作为bitmaps的偏移量c;每次访问和bitmap里面的id进行比较c;如果访问id不在bitmaps里面c;进行拦截c;不允许访问。
3、布隆过滤器
(1) 是1970年由布隆提出的。它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。
布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法c;缺点是有一定的误识别率和删除困难。)
将所有可能存在的数据哈希到一个足够大的bitmaps中c;一个一定不存在的数据会被 这个bitmaps拦截掉c;从而避免了对底层存储系统的查询压力
4.实时监控
当发现redis的命中率开始急速降低c;需要排查访问对象和访问的数据c;和运维人员配合c;可以设置黑名单限制服务
1、数据库的访问压力瞬间加大
2、redis里并没有出现大量key过期
3、redis正常运行
原因:
1、redis中某个keyc;但是这个key是热点keyc;redis就去查数据库c;热点查询c;就让数据库压力过大
解决问题:
1、==预先设置热门数据:==在redis高峰访问之前c;把一些热门数据提前存入到redis里面c;加大这些热门数据key的时长
2、**实时调整:**现场监控哪些数据热门c;实时调整key的过期时长
3、使用锁
肯定能解决问题c;但是会拉低效率
(1) 就是在缓存失效的时候(判断拿出来的值为空)c;不是立即去load db。
(2) 先使用缓存工具的某些带成功操作返回值的操作(比如redis的SETNX)去set一个mutex key
(3) 当操作返回成功时c;再进行load db的操作c;并回设缓存,最后删除mutex key;
(4) 当操作返回失败c;证明有线程在load dbc;当前线程睡眠一段时间再重试整个get缓存的方法。
总结
随着业务发展的需要c;原单体单机部署的系统被演化成分布式集群系统后c;由于分布式系统多线程、多进程并且分布在不同机器上c;这将使原单机部署情况下的并发控制锁策略失效c;单纯的Java API并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问c;这就是分布式锁要解决的问题!
分布式锁主流的实现方案:
基于数据库实现分布式锁
基于缓存(redis等)
基于Zookeeper
每一种分布式锁解决方案都有各自的优缺点:
性能:redis最高
可靠性:zookeeper最高 这里c;我们就基于redis实现分布式锁
setnx u1 100 #创建锁
dl ui #释放锁
给锁设置过期时间
expire ui 10 #过期就失效
这不是一个原子操作c;如果在两个命令之间出现bug之后c;就无法设置时间
使用原子命令
# 上锁 过期时间
set urs 10 nx ex 13
使用redisson
redis的儿子
使用redisson进行锁续命
路标
bilibili视频地址:https://www.bilibili.com/video/BV1sK4y1x749?p=2
redis ACL是Access Control List(访问控制列表)的缩写c;该功能允许根据可以执行的命令和可以访问的键来限制某些连接。
在redis 5版本之前c;redis 安全规则只有密码控制 还有通过rename 来调整高危命令比如 flushdb c; KEYS* c; shutdown 等。redis 6 则提供ACL的功能对用户进行更细粒度的权限控制 :
参考官网:https://redis.io/topics/acl
简介
redis6终于支撑多线程了c;告别单线程了吗? IO多线程其实指客户端交互部分的网络IO交互处理模块多线程c;而非执行命令多线程。redis6执行命令依然是单线程。
原理
redis 6 加入多线程,但跟 Memcached 这种从 IO处理到数据访问多线程的实现模式有些差异。redis 的多线程部分只是用来处理网络数据的读写和协议解析c;执行命令仍然是单线程。之所以这么设计是不想因为多线程而变得复杂c;需要去控制 key、lua、事务c;LPUSH/LPOP 等等的并发问题。
另外c;多线程IO默认也是不开启的c;需要再配置文件中配置 io-threads-do-reads yes io-threads 4
1、什么业务场景下使用mysqlc;什么业务场景下用redis
mysql是关系型数据库c;存储结构清晰的数据放在mysql里c;存重要的东西放在mysql里
redis是非关系型数据库c;无结构c;速度快c;一般是用来作缓存
msyql可以进行复杂的多表联查c;而redis则实现比较麻烦c;只能通过代码实现
2、redis是单线程还是多线程c;为什么使用单线程c;可以用多线程吗
因为redis性能很好c;是靠缓存运行c;单线程可以处理所有并发c;不需要使用多线程
貌似不可以c;我看了很多资料c;因为他速度不快c;不需要设置多线程
3、你们拿redis是当数据库的吗
不是c;作缓存用的
缓存c;分布式锁c;社交c;消息c;用的都比较多
String的最大长度是512m
hash可以存42亿个键值对
6、举一个业务场景redis使用过程中什么时候用hashc;什么时候用list
就比如说短信验证c;有一个keyc;字段里放着手机号或者验证码c;点击注册的时候c;从key里获取值c;验证手机号c;做列表的时候用list比较多c;直接把列表当作集合存入缓存
为什么很少用String
字符串存储有大小c;超过就不能用了
字符串类型key容易重复c;hash的key不容易重复
7、redis作缓存的时候c;如果数据发送改变的话c;怎么同步?
只要程序列表方法使用了缓存c;在更新方法中放入更新redis数据操作c;只要一更新c;就会触发更新缓存c;其实就是删除重新获取
8、redis当中每次加一c;一个原生的方法比get后加一 再set会快一点c;你知道这个方法吗
用incr命令实现命令行让redis数据自增c;java代码是调用redistemplate的一个自增方法c;也很简单
9、加入购物车c;总共有十个商品都加入到了购物车中c;其他还呢能加入吗c;购买完成后怎么减库
未登录的情况下c;购物车的增减都是操作cookiec;登陆成功后才是操作redisc;点击加。前台发送一个ajax请求c;先获取redis或者cookie当中的数据c;得到购物车数据c;给对应数据+1
每次操作cookie或者redisc;速度都很快c;不需要担心速度问题
10、redis持久化做过吗
做过c;有aof和rdb两种方式
rdb是以快照形式c;定期持久化c;是默认的c;编辑redis.conf文件 有save开头的三行数据
save代表保存c;
save 900 1 代表900秒内如果一个key被修改到900秒这些数据将会保存
如何关闭
将三个save注释掉即可
aof是执行增删改之后c;命令都存储在文件中c;数据恢复的时候执行一遍就行
appendonly yes #启动aof持久化
appendfsync everysec #每秒钟强制写入磁盘一次c;在性能和持久化方面做了很好的折中c;推荐
appendfsync always #每次收到写命令就立即强制写入磁盘c;最慢的c;但是保证完全的持久化c;不推荐使用
11、你们公司使用的都是什么持久化
两种都开启c;快照在宕机之后使用c;日志模式恢复比较慢c;
混合用能在一定程度下保证数据安全c;两个配合c;既保证了恢复速度c;也保证了数据不丢失
12、说下redis处理高并发时如何应用
对redis并没有深入学习c;但在网上看过几篇博客c;有一种方法是多路IO复用
13、用过其他缓存吗c;
mybatis缓存说一下
14、memcached 了解吗 说下区别
不是很了解c;只是了解他们的区别
1。memcached 只能存储简单的字符串数据类型c;
2。memcached 和redis都是内存缓存c;但是他宕机后数据不可恢复
3。性能都是一样的
被攻击一般都是一个或者多个ip高频反刷服务器c;判断这个ip高频访问c;我就把他存入数据库一个小时c;把这个ip封锁。然后给前台返回一个访问频繁c;
立马重启c;redis有持久化机制c;数据不会丢失c;排查日志c;如果是并发就加服务器c;bug就调试bugc;黑客攻击就杀ipc;能力允许就搭集群
redis击穿c;首先redis的key没有失效c;错误的urlc;错误的请求c;redis没有c;大量请求访问数据库c;导致数据库压力过大c;我们使用最多的就是布隆过滤器了
18、redis事务有了解过吗
看上面事务详情
19、redis分布式锁
上面redis分布式锁
setnx的使用
https://blog.csdn.net/lihao21/article/details/49104695
景redis使用过程中什么时候用hashc;什么时候用list
就比如说短信验证c;有一个keyc;字段里放着手机号或者验证码c;点击注册的时候c;从key里获取值c;验证手机号c;做列表的时候用list比较多c;直接把列表当作集合存入缓存
为什么很少用String
字符串存储有大小c;超过就不能用了
字符串类型key容易重复c;hash的key不容易重复
7、redis作缓存的时候c;如果数据发送改变的话c;怎么同步?
只要程序列表方法使用了缓存c;在更新方法中放入更新redis数据操作c;只要一更新c;就会触发更新缓存c;其实就是删除重新获取
8、redis当中每次加一c;一个原生的方法比get后加一 再set会快一点c;你知道这个方法吗
用incr命令实现命令行让redis数据自增c;java代码是调用redistemplate的一个自增方法c;也很简单
9、加入购物车c;总共有十个商品都加入到了购物车中c;其他还呢能加入吗c;购买完成后怎么减库
未登录的情况下c;购物车的增减都是操作cookiec;登陆成功后才是操作redisc;点击加。前台发送一个ajax请求c;先获取redis或者cookie当中的数据c;得到购物车数据c;给对应数据+1
每次操作cookie或者redisc;速度都很快c;不需要担心速度问题
10、redis持久化做过吗
做过c;有aof和rdb两种方式
rdb是以快照形式c;定期持久化c;是默认的c;编辑redis.conf文件 有save开头的三行数据
save代表保存c;
save 900 1 代表900秒内如果一个key被修改到900秒这些数据将会保存
如何关闭
将三个save注释掉即可
aof是执行增删改之后c;命令都存储在文件中c;数据恢复的时候执行一遍就行
appendonly yes #启动aof持久化
appendfsync everysec #每秒钟强制写入磁盘一次c;在性能和持久化方面做了很好的折中c;推荐
appendfsync always #每次收到写命令就立即强制写入磁盘c;最慢的c;但是保证完全的持久化c;不推荐使用
11、你们公司使用的都是什么持久化
两种都开启c;快照在宕机之后使用c;日志模式恢复比较慢c;
混合用能在一定程度下保证数据安全c;两个配合c;既保证了恢复速度c;也保证了数据不丢失
12、说下redis处理高并发时如何应用
对redis并没有深入学习c;但在网上看过几篇博客c;有一种方法是多路IO复用
13、用过其他缓存吗c;
mybatis缓存说一下
14、memcached 了解吗 说下区别
不是很了解c;只是了解他们的区别
1。memcached 只能存储简单的字符串数据类型c;
2。memcached 和redis都是内存缓存c;但是他宕机后数据不可恢复
3。性能都是一样的
被攻击一般都是一个或者多个ip高频反刷服务器c;判断这个ip高频访问c;我就把他存入数据库一个小时c;把这个ip封锁。然后给前台返回一个访问频繁c;
立马重启c;redis有持久化机制c;数据不会丢失c;排查日志c;如果是并发就加服务器c;bug就调试bugc;黑客攻击就杀ipc;能力允许就搭集群
redis击穿c;首先redis的key没有失效c;错误的urlc;错误的请求c;redis没有c;大量请求访问数据库c;导致数据库压力过大c;我们使用最多的就是布隆过滤器了
18、redis事务有了解过吗
看上面事务详情
19、redis分布式锁
上面redis分布式锁
setnx的使用
https://blog.csdn.net/lihao21/article/details/49104695
以上是大佬教程为你收集整理的什么!Redis不会用!看完这个你就是Redis大牛了!全部内容,希望文章能够帮你解决什么!Redis不会用!看完这个你就是Redis大牛了!所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。