【Redis】
2022/1/7 2:05:18
本文主要是介绍【Redis】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
基本类型
String——字符串 或 Json
缓存:
计数器:
自增ID:
List——LinkedList, 队列:右进左出 。栈:右进右出
异步队列:
任务轮询:
文章列表:
Hash
整个博客的访问人数:
某页墨客的访问量,姓名,联系方式,住址等。
Set
抽奖:随机返回元素
共同关注:交集
Sorted set
排行榜:
订单支付超时:score为订单超时时间戳,然后写个定时任务每隔一段时间执行zrange。
签到——位图数据结构
bitmap储存的是连续的二进制数字。
基本命令:
setbit key [第几位] [0或1]
getbit key [第几位] [0或1]
bitcount key 计数里面为1的个数。
bitcount key starrt end 范围计数,是指字符的下标,所以,是位数的8的整数倍。
bitpos key bit(0或1) [start-字符下标] [end-字符下标]
bitfield:
## 模拟用户2021年7月15日签到,偏移量从0开始 setbit userid:sign:202107 14 1 ## 获取用户2021年7月的签到数据 127.0.0.1:6379> bitfield userid:sign:202107 get u31 0
统计UV——HyperLogLog数据结构
UV 要去重,同一个用户一天之内的多次访问请求只能计数一次。这就要求每一个网页请求都需要带上用户的 ID,无论是登陆用户还是未登陆用户都需要一个唯一 ID 来标识。
方案一:
我们第一反应就是为每一个页面搞一个独立的 set 集合来存储所有当天访问过此页面的用户 ID。当一个请求过来时,我们使用 sadd 将用户 ID 塞进去就可以了。通过 scard 可以取出这个集合的大小,这个数字就是这个页面的 UV 数据。没错,这是一个非常简单的方案。
存在问题:
1:用户ID一个约占32个字节,占用内存过大。
2:数据量大时,sadd性能会下降。
方案二:
HyperLogLog 提供不精确的去重计数方案。
首先得到64位的hash值,用前14位来定位桶的位置(共有 [公式] ,即16384个桶)。后面50位即为伯努利过程,每个桶有6bit,记录第一次出现1的位置count,如果count>oldcount,就用count替换oldcount。
在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
常用命令:
pfadd uv user1 #新元素 pfcount uv #计数
去重——布隆过滤器
当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。
添加布隆过滤器插件:
[root@izuf65itgtxe1lpfpb***** redis]# git clone https://github.com/RedisBloom/RedisBloom.git [root@izuf65itgtxe1lpfpb***** redis]# cd RedisBloom/ [root@izuf65itgtxe1lpfpb***** RedisBloom]# make [root@izuf65itgtxe1lpfpb***** RedisBloom]# vi /usr/local/redis/redis.conf ## 增加配置 loadmodule /usr/local/redis/RedisBloom/redisbloom.so ## 重启redis就行
常用命令:
bf.add bloomFilterKey user1 bf.exists bloomFilterKey user3
添加元素时,先把value转化为字节(getBytes(value,”UTF-8")),通过算法对元素计算出k(14)个独立的hash值,然后用这k个独立的hash值与位图长度( 201978)进行取余,对应位置设置1。
判断元素是否存在,对元素计算出k个独立的hash值,然后用这k个独立的hash值与位图长度(201978)进行取余,所有的位置都是1表示存在,只要有一位为0都是不存在。
注意:位图长度越长错误率越低,但是需要很大的空间,一般这里都是用预计放入元素量,当实际数量超出这个值时,误判率会上升
错误率计算器:https://krisives.github.io/bloom-calculator/
实现:
使用双重校验
if(bloomFilter.exist(data)) { // 2.如果布隆过滤器存在,需要在MySQL中进行二次校验 if(mysqlService.exist(data)) { // 3.数据存在 existFlag = true; } }
布隆过滤器使用场景:
- 黑名单
- 爬虫
- 缓存穿透
Redis单线程为什么这么快
严格来说, Redis Server是多线程的, 只是它的请求处理整个流程是单线程处理的。 这一点我们一定要清楚了解到,不要单纯地认为Redis Server是单线程的。
- Redis大部分操作在内存完成
- 采用IO多路复用机制
- 非CPU密集型任务
- 单线程的优势
1.纯内存操作
内存操作快,数据结构搞笑——hash和跳表。
2.采用IO多路复用机制
文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
3.非CPU密集型任务
采用单线程的缺点很明显,无法使用多核CPU。
Redis的瓶颈在于内存和网络带宽。
在高并发的情况下,可以采用集群,而不是多线程。
4.单线程的优点
- 避免上下文切换
- 避免访问共享资源加锁导致性能损耗
5.单线程的缺点
单线程处理最大的缺点就是,如果前一个请求发生耗时比较久的操作,那么整个Redis都会被阻塞,其他请求也无法进来,直到这个耗时久的操作处理完成并返回,其他请求才能被处理到。
所以,我们在使用Redis时,一定要避免非常耗时的操作,例如使用时间复杂度过高的方式获取数据、一次性获取过多的数据、大量key集中过期导致Redis淘汰key压力变大等等,这些场景都会阻塞住整个处理线程,直到它们处理完成,势必会影响业务的访问。
6.多线程优化
耗时操作采用异步:
- 比如AOP每秒刷盘。——异步
- lazyfree机制,异步释放内存。——异步
- 请求数据的协议解析。——多线程
过期策略
1.惰性删除
访问(读写)时,会检测key是否过期。
2.定期删除
把设置了有效期的key存在一个集合里,默认每秒检测10次,随机抽查20个查看是否过期。
如果比例超过1/4,就重复上述操作。(贪心算法)
为了保证过期扫描不会出现循环过度,线程卡死。增加了扫描时间的上线,25ms。
大量key集中过期导致卡顿,如何解决?
方案一:在设置 key 的过期时间时,增加一个随机时间
redis.expireat(key, expire_time + random(300))
方案二:Redis 4.0 以上版本,开启 lazy-free 机制
lazyfree-lazy-expire yes
内存淘汰机制
当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。 交换会让 Redis 的性能急剧下降。
配置参数 maxmemory 来限制内存超出期望大小。
8种算法:
- noeviction:不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
- volatile-lru:尝试淘汰设置了过期时间的 key,通过LRU算法驱逐最近最少使用的key。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
- volatile-random:尝试淘汰设置了过期时间的 key,在设置了过期时间的key集合中随机选择数据淘汰。
- volatile-ttl:尝试淘汰设置了过期时间的 key,在设置了过期时间的key集合中优先淘汰ttl小的。
- allkeys-lru:和volatile-lru的区别在于要淘汰的key对象是全体key集合而不只是设置了过期时间的key,其他都一样。
- allkeys-random:和volatile-random的区别在于要淘汰的key对象是全体key集合而不只是设置了过期时间的key,其他都一样。
- volatile-lfu:尝试淘汰设置了过期时间的 key,通过LFU算法驱逐使用频率最少的key。没有设置过期时间的 key 不会被淘汰。
- allkeys-lfu:和volatile-lfu的区别在于要淘汰的key对象是全体key集合而不只是设置了过期时间的key,其他都一样。
Redis持久化
RDB:
优点:
- RDB文件紧凑,体积小,网络传输快,适合全量赋值
- RDB最大化了Redis的性能,可以在从节点fork一个子进程。不影响主进程
缺点:
- 快照是定期生成,损失数据较多。
- 当数据量较大时,fork 的过程是非常耗时的,fork 子进程时是会阻塞的,在这期间 Redis 是不能响应客户端的请求的。
AOF:
优点:
- 数据安全性高
- AOP文件易读,可修改。
缺点:
- 文件过大,即使通过AOF重写,文件体积依然很大。
- 数据恢复速度比RDB慢。
混合持久化:
开启混合持久化时,fork出的子进程先将共享的内存副本全量的以 RDB 方式写入 AOF 文件。
然后在将重写缓冲区的增量命令以 AOF 方式写入到文件。
简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据。
主从复制
- 全量复制
- 增量复制
- 无盘复制
哨兵
1.状态感知
2.心跳检测
3.主观下线和客观下线——n/2+1
4.选举哨兵领导者——随机超时时间
5.谁来做master——优先级配置>数据完整性>runid较小
6.通知客户端
Redis集群
1.数据如何分片 ——虚拟槽分区–所有实例共用16834个槽位
2.MOVED和ASK的共同点: 两者都是重定向
MOVED和ASK的不同点
MOVED:槽已经确定
ASk:槽在迁移过程中,key有可能在source节点有可能在target节点
3.槽位迁移感知:
客户端保存了槽位和节点的映射关系表,当客户端收到moved指令的时候,他会去刷新槽位映射关系表,获取到最新的映射关系。当收到ask转向异常时,不会刷新槽位映射关系表,因为它是临时纠正。
Redis分布式锁
这篇关于【Redis】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-07Redis高并发入门详解
- 2024-12-07Redis缓存入门:新手必读指南
- 2024-12-07Redis缓存入门:新手必读教程
- 2024-12-07Redis入门:新手必备的简单教程
- 2024-12-07Redis入门:新手必读的简单教程
- 2024-12-06Redis入门教程:从安装到基本操作
- 2024-12-06Redis缓存入门教程:轻松掌握缓存技巧
- 2024-12-04Redis入门:简单教程详解
- 2024-11-29Redis开发入门教程:从零开始学习Redis
- 2024-11-27Redis入门指南:快速掌握Redis基础操作