Redis的基本知识

2020-01-05  本文已影响0人  掩流年

Redis的基本原理

Redis是单线程程序,它快的原因是因为它是在内存中运行的,它的多路复用技术保证了保证了并发客户端的连接。

NIO

NIO又被称为Non_Blocking IO。对于普通的IO而言,在一个socket对象进行网络传输的读写时候,当读操作读取的byte数还没有达到读取的要求就会被阻塞住,直到新的数据来到或者等连接关闭。对于写操作,内核为写缓冲分配的内存满了,就会发生阻塞。

对于NIO而言,一次性能读多少就读多少,读完之后立即返回,写操作也是一样。但是这样如何保证数据读取和写入的完整性呢?这就用到了多路复用技术。

多路复用

其实从本质上而言就是,操作系统内核为程序分配了一个线程API叫做“select”,或者也linux中也有一种线程叫做“epoll”。它一只轮询着去看有没有新的时事件返回过来,有的话就赶紧通知redis的线程过来处理。
对多个客户端而言,多路复用中维护了一个指令队列,把客户端放进去,按顺序进行处理。
在轮询的同时,它们也会有timeout的一个属性,表示在一个事件等待的超时事件。这个时间的计算是动态的。是在定时任务中有个最小堆的数据结构。判断最先要执行的事件还需要多长时间,这个等待事件就是timeout时间。

持久化

Redis在持久化中,会使用操作系统的多进程COW(Copy On Write)来实现。

Redis也可以使用混合持久化的方式,在实际运维中,持久化操作总是在从节点上进行的。但是Reids本来就不是强一致性的,所以无论采用什么方式,当机器突然宕机的时候总会丢失一些数据。

Redis的数据结构

String

string是动态字符串,小于1M的时候每次扩容都是翻倍的,大于1M每次扩容都是加1M。可以认为它是一个ArrayList结构,有个常见的用途是我们可以使用fastjson把用户结构体序列化成字符串形式,然后做缓存。

expire name 5 //可以用来设置过期时间5s

setnx name 1 /会先检测有没有name这个key,有则输入失败,没有则添加成功

list

redis中的list相当于Java中的LinkedList,它是链表结构。当使用的键值对过多的情况下, 会产生较多的内存碎片。所以list中有一种列表叫做快速列表,就是在内存足够的时候分配一串连续的内存,叫做ziplist。

hash

更hashmap的结构基本是类似的,只是rehash的方式是不一致的,Redis为了高性能,不阻塞服务使用的是渐进式rehash策略。当hash移除了最后一个元素,就会删除原来旧的数据结构。

set

set集合相当于Java中的HashSet,可以用来存储中奖用户,它的内部键值都是无序且唯一的。

Redis实现分布式锁

redis实现分布式锁最简单的方式是

setnx lock 1

expire lock 5

死锁问题

但是因为这两步操作并非原子性的,所以在Redis2.8之后提供了一种方式:

set lock:codehole true ex 5 nx

超时问题

给每个set操作的value值加一个随机数,当锁释放的时候先比较这个随机数是否一致,一致的话则进行del操作。

位图

位图的操作是setbit,getbit。可以指定一个string的ASCII码的位数。

HyperLogLog

使用pfadd和pfcount来提供不精确的统计方案,它可以用来统计日常的pv和uv。

布隆过滤器

在推荐算法中,过滤掉那些你看过的资讯。

bf.add test movie1
bf.exist test movie1
(integer) 1
bf.exist test movie2
(integer) 0

布隆过滤器的原理其实是一个大型的位数组和几个不一样的无偏hash函数。在每次添加key的时候, 利用hash函数算的位数组的索引,然后把这一位置为1。

简单的限流

限流的策略可以使用zset中的score数据结构,可以使用score的排序功能,划出一个时间窗口。简单的使用pipeline实现限流。

漏斗限流

可以使用开源插件redis-cell实现原子性操作

SCAN

1.通过游标分步进行的,不会阻塞线程
2.提供limit参数,可以控制每次返回结果的最大条数。
3.可以提供模式匹配功能
4.返回的结果可能会有重复,需要客户端去重
5.遍历的过程中,如果有数据的修改,改动过的数据有没有被遍历到是不知道的。
6.单次返回的结果为空并不意味着遍历的结束,而是要看返回的游标值是否为零。

上一篇 下一篇

猜你喜欢

热点阅读