热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis要知道的一点东西(二)

实践篇数据的适量存储1、String类型的短板?String消耗内存大2、为什么String类型内存开销大?String类型还需要额外的内存空间记录数据长度、空间使用等信息,这些信

实践篇

数据的适量存储


1、String 类型的短板?

String 消耗内存大


2、为什么 String 类型内存开销大?

String 类型还需要额外的内存空间记录数据长度空间使用等信息,这些信息也叫作元数据。当实际保存的数据较小时,元数据的空间开销就显得比较大了。


3、SDS(简单动态字符串)的结构

image-20210203085923544



  • buf:字节数组,保存实际数据,会在最后面加一个 \0,多占用一个字节

  • len:占用四个字节,表示buf的已用长度

  • alloc:占用四个字节,表示buf的实际长度,一般大于 len


4、什么是Redis Object?

因为 Redis 的数据类型有很多,而且,不同数据类型都有些相同的元数据要记录(比如最后一次访问的时间、被引用的次数等),所以,Redis 会用一个 RedisObject 结构体来统一记录这些元数据,同时指向实际数据。


5、Redis Object 的结构是什么样的?

8 byte 的元数据以及 8 byte的指针(ptr),指针指向具体数据类型的实际数据所在地址,redis object 对 sds 做了单独的优化,如果存入的是:



  • long 整型数组的时候,ptr 为具体的值

  • 如果是字符串类型,且小于 44 byte,元数据、指针和sds是一块连续的内存,并用指针指向sds,raw 编码模式

  • 其他则为指针查找模式

img


6、dictEntry 啥样子?

dictEntry 结构中有三个 8 字节的指针,分别指向 key、value 以及下一个 dictEntry,三个指针共 24 字节:

img


7、Redis 内存申请方式

使用内存分配库 jemallloc,jemalloc 在分配内存时,会根据我们申请的字节数 N,找一个比 N 大,但是最接近 N 的 2 的幂次数作为分配的空间,这样可以减少频繁分配的次数。


8、保存小数据的时候可以用什么数据结构保存,在Redis中?

压缩列表


9、压缩列表保存数据的结构是什么样的?

压缩列表由一些元数据与真正存储数据的 entry 构成,entry包含以下结构:



  • prev_len:如果上一个 entry 长度小于 254(255被zlend当成默认值使用了,表示压缩列表的结束) 字节,则此值为 1字节,大于254 则采用 5 字节

  • len:表示自身的长度,4字节

  • encoding:表示编码方式 1字节

  • content:保存实际数据


10、Hash 结构压缩列表与 hash 结构的转换



  • hash-max-ziplist-entries:表示用压缩列表保存时哈希集合中的最大元素个数。

  • hash-max-ziplist-value:表示用压缩列表保存时哈希集合中单个元素的最大长度。

超过这俩阈值其中的一个就会由压缩列表转化为 hash 存储了


11、常见的集合统计模式有哪些?



  • 聚合统计

  • 排序统计

  • 二值统计 bitmap

  • 基数统计 hyperloglog pfadd pfcount 有误算率 0.81%


12、GEO 是怎么实现的?

GEO 类型的底层数据结构就是用 Sorted Set 来实现的,采用的是 GeoHash 编码,基本原理就是 二分区间,区间编码

当我们要对一组经纬度进行 GeoHash 编码时,我们要先对经度和纬度分别编码,然后再把经纬度各自的编码组合成一个最终编码。


13、GeoHash 编码是怎么计算的?



  • 先从单独对经度与维度编码来看

    • 对于一个地理位置信息来说,它的经度范围是[-180,180]。GeoHash 编码会把一个经度值编码成一个 N 位的二进制值,我们来对经度范围[-180,180]做 N 次的二分区操作,其中 N 可以自定义。

    • 在进行第一次二分区时,经度范围[-180,180]会被分成两个子区间:[-180,0) 和[0,180](可称之为左、右分区)。此时,我们可以查看一下要编码的经度值落在了左分区还是右分区。如果是落在左分区,我们就用 0 表示;如果落在右分区,就用 1 表示。这样一来,每做完一次二分区,我们就可以得到 1 位编码值。

    • 重复之前的操作,每次都能获得一位编码,等做完 N 次之后就可以用一个 N bit 的数来表示了

    • 对维度也是一样,只不过维度的范围是[-90,90]



  • 等经纬度都编码完之后,再组合到一起,组合的规则是,偶位数上依次是经度的编码值,奇位数上是维度的编码值,由此得到 sort set 的权重

为了避免查询不准确问题,可以同时查询给定经纬度所在的方格周围的 4 个或 8 个方格


14、分布式组件消息队列的需求?



  • 消息保序

  • 重复消费处理

  • 消息可靠性保证


影响 Redis 性能的潜在方面


15、与 Redis 交互发生的操作



  • 客户端:网络 IO,键值对增删改查操作,数据库操作;

  • 磁盘:生成 RDB 快照,记录 AOF 日志,AOF 日志重写;

  • 主从节点:主库生成、传输 RDB 文件,从库接收 RDB 文件、清空数据库、加载 RDB 文件;

  • 切片集群实例:向其他实例传输哈希槽信息,数据迁移。


16、Redis 的阻塞点有哪些?



  • 客户端交互阻塞点

    • 客户端的复杂操作,集合全量查询和聚合操作。

    • bigkey 的删除操作

    • **清空数据库 ** FLUSHDB\FLUSHALL



  • 和磁盘交互时的阻塞点

    • AOF 日志同步写



  • 主从节点交互时的阻塞点

    • 从节点加载RDB 文件




17、redis的删除操作?

删除操作的本质是要释放键值对占用的内存空间。在应用程序释放内存时,操作系统需要把释放掉的内存块插入一个空闲内存块的链表,以便后续进行管理和再分配。这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序,所以,如果一下子释放了大量内存,空闲内存块链表操作时间就会增加,相应地就会造成 Redis 主线程的阻塞。


18、redis 解决部分阻塞点的方式?

异步的子线程机制,利用操作系统 pthread_create 函数创建 3 个子线程,分别负责 aof 的写操作、键值对删除以及文件关闭的异步执行。

主线程通过一个链表形式的任务队列和子线程进行交互。



  • aof 被封装成一个任务放入队列,异步执行

  • 异步删除,惰性删除,即使开启了lazy-free,如果直接使用DEL命令还是会同步删除key,只有使用UNLINK命令才会可能异步删除key。

  • 清空数据库用 flushdb async


19 、lazy_free 是个什么东西?

lazy-free是4.0新增的功能,但是默认是关闭的,需要手动开启。



  • lazyfree-lazy-expire:key在过期删除时尝试异步释放内存

  • lazyfree-lazy-eviction:内存达到maxmemory并设置了淘汰策略时尝试异步释放内存

  • lazyfree-lazy-server-del:执行RENAME/MOVE等命令或需要覆盖一个key时,删除旧key尝试异步释放内存

  • replica-lazy-flush:主从全量同步,从库清空数据库时异步释放内存

lazy_free 也不是一直生效的,除了 replica-lazy-flush 以外都只是可能释放;

开启lazy-free后,Redis在释放一个key的内存时,首先会评估代价,如果释放内存的代价很小,那么就直接在主线程中操作了,没必要放到异步线程中执行(不同线程传递数据也会有性能消耗)。


20、什么情况 lazy_free 才会真正异步释放内存?



  • 当Hash/Set底层采用哈希表存储(非ziplist/int编码存储)时,并且元素数量超过64个

  • 当ZSet底层采用跳表存储(非ziplist编码存储)时,并且元素数量超过64个

  • 当List链表节点数量超过64个(注意,不是元素数量,而是链表节点的数量,List的实现是在每个节点包含了若干个元素的数据,这些元素采用ziplist存储)

只有以上这些情况,在删除key释放内存时,才会真正放到异步线程中执行,其他情况一律还是在主线程操作。

也就是说String(不管内存占用多大)、List(少量元素)、Set(int编码存储)、Hash/ZSet(ziplist编码存储)这些情况下的key在释放内存时,依旧在主线程中操作。


21、主流的 CPU 架构

主流 CPU 有物理核,逻辑核,一个 cpu 组成一个 socket,多个cpu通过总线通信,这种架构叫 NUMA 架构(非统一内存访问架构);

在多 CPU 架构上,应用程序可以在不同的处理器上运行

d9689a38cbe67c3008d8ba99663c2f09

在主流的服务器上,一个 CPU 处理器会有 10 到 20 多个物理核。同时,为了提升服务器的处理能力,服务器上通常还会有多个 CPU 处理器(也称为多 CPU Socket),每个处理器有自己的物理核(包括 L1、L2 缓存),L3 缓存,以及连接的内存,同时,不同处理器间通过总线连接。

5ceb2ab6f61c064284c8f8811431bc3d


22、什么是尾延迟?

们把所有请求的处理延迟从小到大排个序,99% 的请求延迟小于的值就是 99% 尾延迟。


23、context switch

context switch 是指线程的上下文切换,这里的上下文就是线程的运行时信息。


24、redis 绑核

# -c 表示要绑定的核号
taskset -c 0 ./redis-server

25、绑核的好处?



  • 降低尾延迟

  • 降低平均延迟

  • 提升吞吐率


26、绑核的风险

当把 Redis 实例绑定到一个逻辑核的时候,会导致后台线程、进程与 Redis 主进程争抢CPU,主线程就会被阻塞,导致 Redis 延迟增加


27、怎么解决绑核的问题?



  • Redis 实例对应绑一个物理核

  • 优化 Redis 源码。

# 绑定0、12 逻辑核,其实是一个物理核
taskset -c 0,12 ./redis-server

28、怎么检测 Redis 的响应延迟?

./redis-cli --intrinsic-latency 120

29、过期 key 操作

默认情况下,Redis 每 100 毫秒会删除一些过期 key



  • 采样 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP (默认20)个数的 key,并将其中过期的 key 全部删除;

  • 如果超过 25% 的 key 过期了,则重复删除(阻塞)的过程,直到过期 key 的比例降至 25% 以下。

为了防止同一时间大量的key过期,给同一批次的数据加上随机过期时间是个不错的选择


30、替代 keys 的 sacn 命令有什么好处跟问题?



  • 不会漏key:Redis在SCAN遍历全局哈希表时,采用高位进位法的方式遍历哈希桶,当哈希表扩容后,通过这种算法遍历,旧哈希表中的数据映射到新哈希表,依旧会保留原来的先后顺序,这样就可以保证遍历时不会遗漏也不会重复。

  • 可能会得到重复的key:在 hash 桶缩容的时候,会将扫描过的key映射到hash表还没遍历的地方,所以会重复

scan 是针对所有key的,redis 针对 hash/set/sorted set 也提供了对应的 scan 命令,用于遍历一个key 所有的 value,但是 hscan、sscan、zscan 如果数据比较少的话,底层采用 intset\ziplist ,命令会无视 count 参数,将所有的数据都返回出来


31、什么是 hash tag?

在键值对的key中使用花括号{},例如{user:}1, {user:}2这样。Redis cluster会针对花括号中的部分进行哈希,这样可以把具有相同前缀的key分配到同一个哈希槽里面。

可能会导致数据分布不均衡


32、AOF 数据的流动方向?

aof 依赖 write 与 fsync 两个系统调用



  • write 只需要把日志写到内核缓冲区就可以返回了

  • fsync 需要把日志记录写到磁盘才能返回,时间较长


33、不同 AOF 策略对应系统调用



  • no 对应 write,由操作系统来保证刷盘

  • everysec 对应 redis 子线程来调用 fsync ,不阻塞主线程

  • always 对应着 fsync,由主线程调用


34、Redis 使用 fsync 的阻塞点?



  • fsync需要等到数据写入磁盘才能返回,aof 重写对磁盘 io 压力过大时,就会导致 fsync 阻塞,虽然 fsync 是子线程去做,但是主线程要监控执行的进度。

  • 当主线程使用 子线程 执行了一次 fsync,需要再次把数据写回磁盘的时候,发现上次的fsync还没进行完,则阻塞主线程


35、怎么让 aof 重写与 fsync 分离?

如果业务应用对延迟非常敏感,但同时允许一定量的数据丢失,那么可以关闭在 aof 时调用 fsync

no-appendfsync-on-rewrite yes

这个配置项设置为 yes 时,表示在 AOF 重写时,不进行 fsync 操作。如果设置为 no 的话,redis 实例仍然会调用后台线程进行 fsync,会给实例带来阻塞。


36、什么是 swap?

内存 swap 是操作系统里将内存数据在内存和磁盘间来回换入和换出的机制,涉及到磁盘的读写,所以,一旦触发 swap,无论是被换入数据的进程,还是被换出数据的进程,其性能都会受到慢速磁盘读写的影响。


37、什么时候会触发 swap?

物理机器内存不足



  • Redis 实例自身使用了大量的内存,导致物理机器的可用内存不足;

  • 和 Redis 实例在同一台机器上运行的其他进程,在进行大量的文件读写操作。文件读写本身会占用系统内存,这会导致分配给 Redis 实例的内存量变少,进而触发 Redis 发生 swap。

可以增加机器内存或者使用redis cluster


38、系统大页会给 Redis 带来什么问题?

因为 redis 大量采用 COW(写时复制)的操作,如果使用系统大页,会将原本只拷贝 4KB 的数据变成拷贝 2MB,影响 Redis 正常的存取操作。

# always 为启动,never 为关闭
cat /sys/kernel/mm/transparent_hugepage/enabled
# 部署时关闭系统大页
echo never /sys/kernel/mm/transparent_hugepage/enabled

39、如何分析、排查、解决Redis变慢问题?


1、使用复杂度过高的命令


(例如SORT/SUION/ZUNIONSTORE/KEYS),或一次查询全量数据(例如LRANGE key 0 N,但N很大)


分析:



  • 查看slowlog是否存在这些命令

  • Redis进程CPU使用率是否飙升(聚合运算命令导致)

解决:



  • 不使用复杂度过高的命令,或用其他方式代替实现(放在客户端做)

  • 数据尽量分批查询(LRANGE key 0 N,建议N<=100,查询全量数据建议使用HSCAN/SSCAN/ZSCAN)


2、操作bigkey

分析:



  • slowlog出现很多SET/DELETE变慢命令(bigkey分配内存和释放内存变慢)

  • 使用redis-cli -h $host -p $port --bigkeys扫描出很多bigkey

解决:



  • 优化业务,避免存储bigkey

  • Redis 4.0+可开启lazy-free机制


3、大量key集中过期

分析:



  • 业务使用EXPIREAT/PEXPIREAT命令

  • Redis info中的expired_keys指标短期突增

解决:



  • 优化业务,过期增加随机时间,把时间打散,减轻删除过期key的压力

  • 运维层面,监控expired_keys指标,有短期突增及时报警排查


4、Redis内存达到maxmemory

分析:



  • 实例内存达到maxmemory,且写入量大,淘汰key压力变大

  • Redis info中的evicted_keys指标短期突增

解决:



  • 业务层面,根据情况调整淘汰策略(随机比LRU快)

  • 运维层面,监控evicted_keys指标,有短期突增及时报警

  • 集群扩容,多个实例减轻淘汰key的压力


5、大量短连接请求

分析:



  • Redis处理大量短连接请求,TCP三次握手和四次挥手也会增加耗时

解决:



  • 使用长连接操作Redis


6、生成RDB和AOF重写fork耗时严重

分析:



  • Redis变慢只发生在生成RDB和AOF重写期间

  • 实例占用内存越大,fork拷贝内存页表越久 c) Redis info中latest_fork_usec耗时变长

解决:



  • 实例尽量小

  • Redis尽量部署在物理机上

  • 优化备份策略(例如低峰期备份)

  • 合理配置repl-backlog和slave client-output-buffer-limit,避免主从全量同步

  • 视情况考虑关闭AOF

  • 监控latest_fork_usec耗时是否变长


7、AOF使用awalys机制

分析:



  • 磁盘IO负载变高

解决:



  • 使用everysec机制

  • 丢失数据不敏感的业务不开启AOF


8、使用Swap

分析:



  • 所有请求全部开始变慢

  • slowlog大量慢日志

  • 查看Redis进程是否使用到了Swap

解决:



  • 增加机器内存

  • 集群扩容

  • Swap使用时监控报警


9、进程绑定CPU不合理

分析:



  • Redis进程只绑定一个CPU逻辑核

  • NUMA架构下,网络中断处理程序和Redis进程没有绑定在同一个Socket下

解决:



  • Redis进程绑定多个CPU逻辑核

  • 网络中断处理程序和Redis进程绑定在同一个Socket下


10、开启透明大页机制

分析:



  • 生成RDB和AOF重写期间,主线程处理写请求耗时变长(拷贝内存副本耗时变长)

解决:



  • 关闭透明大页机制


11、网卡负载过高

分析:



  • TCP/IP层延迟变大,丢包重传变多

  • 是否存在流量过大的实例占满带宽

解决:



  • 机器网络资源监控,负载过高及时报警

  • 提前规划部署策略,访问量大的实例隔离部署


内存整理


40、如何判断是否有内存碎片?

info memory 命令里面的 mem_fragmentation_ratio指标就是 Redis 当前的内存碎片率

used_memory_rss 表示操作系统分配给 Redis 物理内存空间,里面包含了碎片,used_memory 表示 Redis 申请了多少空间 mem_fragmentation_ratio = used_memory_rss/ used_memory


41、怎么判断是否超过了阈值?



  • mem_fragmentation_ratio 大于 1 但小于 1.5。这种情况是合理的。

  • mem_fragmentation_ratio 大于 1.5 。这表明内存碎片率已经超过了 50%。一般情况下,这个时候,我们就需要采取一些措施来降低内存碎片率了。


42、如何清理内存碎片?



  • 重启

  • 4.0-RC3 版本以后,有自动清理的功能,压缩内存


43、Redis 怎么开启自动清理?

# 开启自动清理配置
config set activedefrag yes

44、redis 什么时候自动清理?



  • active-defrag-ignore-bytes 100mb:表示内存碎片的字节数达到 100MB 时,开始清理;

  • active-defrag-threshold-lower 10:表示内存碎片空间占操作系统分配给 Redis 的总空间比例达到 10% 时,开始清理。

为了减轻自动清理对主线程的影响,redis 设置了两个参数用来保证:



  • active-defrag-cycle-min 25:表示自动清理过程所用 CPU 时间的比例不低于 25%,保证清理能正常开展;

  • active-defrag-cycle-max 75:表示自动清理过程所用 CPU 时间的比例不高于 75%,一旦超过,就停止清理,从而避免在清理时,大量的内存拷贝阻塞 Redis,导致响应延迟升高。


45、客户端为什么需要用到缓冲区?



  • 一方面,可以在客户端控制发送速率,避免把过多的请求一下子全部发到 Redis 实例,导致实例因压力过大而性能下降。不过,客户端缓冲区不会太大,所以,对 Redis 实例的内存使用没有什么影响。

  • 另一方面,在应用 Redis 主从集群时,主从节点进行故障切换是需要一定时间的,此时,主节点无法服务外来请求。如果客户端有缓冲区暂存请求,那么,客户端仍然可以正常接收业务应用的请求,这就可以避免直接给应用返回无法服务的错误。

库上的从库输出缓冲区(slave client-output-buffer)是不计算在Redis使用的总内存中的,也就是说主从同步延迟,数据积压在主库上的从库输出缓冲区中,这个缓冲区内存占用变大,不会超过maxmemory导致淘汰数据。只有普通客户端和订阅客户端的输出缓冲区内存增长,超过maxmemory时,才会淘汰数据。


46、怎么使用 redis 的慢日志?

设置阈值:



  • slowlog-log-slower-than:慢查询日志对执行时间大于多少微秒的命令进行记录。

  • slowlog-max-len:记录多少条数,默认128,建议改成1k,底层是队列实现,超过阈值则被删除

slowlog get 1

47、如何排查 Redis 的 bigkey?

# 对整个数据库中的键值对大小情况进行统计分析
./redis-cli --bigkeys

48、Redis 做缓存的时候,缓存的类型有哪些?



  • 只读缓存 修改数据则删掉缓存中的数据

  • 读写缓存


49、怎么解决 Redis 做读写缓存时的缺陷?



  • 可靠性保证:同步直写。写请求发给缓存的同时,也会发给后端数据库进行处理,等到缓存和数据库都写完数据,才给客户端返回。速度慢。

  • 快速响应:异步写回。所有写请求都先在缓存中处理,等到这些增改的数据要被从缓存中淘汰出来时,缓存将它们写回后端数据库。如果掉电则丢失数据。


50、怎么设置 Redis 缓存的大小?

conifg set maxmemory 4gb

一般建议设置成总数据量的15% - 30%


51、缓存淘汰策略?

noeviction、volatile-ttl、volatile-random、volatile-lru、volatile-lfu、allkeys-lru、allkeys-lfu、allkeys-random


52、Redis 中的 Lru 算法有啥区别?

LRU 算法被做了简化,Redis会将最近访问时的时间戳记录在 Redis Object 中 lru 字段中,redis 执行定期淘汰策略,第一次选出 N 个数据,把其当成一个候选集合,然后比较这 N 个数据的 lru 的值,把 lru 最小的值淘汰出去。

# 设置 N 的大小,默认是5,建议改为10
CONFIG SET maxmemory-samples 10
# 容量大小
evictionPoolEntry 的容容量是 EVPOOL_SIZE = 16;


  • 当再次进行定期淘汰的时候,再挑选一批新的数据,但是能进入集合的只有 lru 小于现集合最小的 lru 的值才可以,当达到了 maxmemory-samples 的值后,redis 把集合中lru最小的值踢掉。

  • 每次淘汰的数量是根据内存量超过 maxmemory 的情况来决定的,所以每次加进集合的数据量也不是只有一个。

  • 准备要淘汰的数据与淘汰数据是两个操作

  • 当淘汰集合中没有位置的时候,新进来的数据小于最小 lru,集合头部存放的是最大的 lru,所以会把头部的数据依次移出集合,将更古老的数据存放到集合链表的尾部。


53、什么是缓存污染?

仅仅被访问少数次的数据被大量放在缓存里面


54、LFU 缓存策略的优化

LFU 缓存策略是在 LRU 策略基础上,为每个数据增加了一个计数器,来统计这个数据的访问次数。当使用 lfu 策略的时候,首先根据计数器筛选,把访问次数最低的淘汰出去,如果两个数据访问次数相同,则比较时间戳,淘汰最小的。


55、LFU 是怎么计算出数据的?

Redis 在实现 LFU 策略的时候,只是把原来 24bit 大小的 lru 字段,又进一步拆分成了两部分。



  • 前16位为访问的时间戳

  • 后8位为数据访问的次数


56、8 位最高才255,LFU 是怎么做的?

使用 非线性递增的计数器方法

double r = (double)rand()/RAND_MAX;
// baseval是计数器,初始默认值是 5,LFU_INIT_VAL 常量设置,避免数据刚被写入缓存,就因为访问次数少而被立即淘汰
double p = 1.0/(baseval * server.lfu_log_factor + 1);
if (r

57、LFU 的衰减策略是什么?

Luf 的次数不能只加不减,所以有衰减策略,如果 lfu_decay_time 为 1 的话,N 分钟就要被减 N,如果设置的很大则会衰减的缓慢很多。


58、Redis 针对过期数据的删除策略有哪些?



  • 惰性删除

  • 定期删除

  • 定时删除


60、Redis 主从模式下过期数据有什么问题?



  • 惰性删除时,访问从库并不会触发主库的删除策略,3.2 以前读取过期数据,从库会返回过期数据,3.2 以后返回空值

  • EXPIRE 和 PEXPIRE:它们给数据设置的是从命令执行时开始计算的存活时间,可能会导致数据延迟

可以使用 EXPRIEAT / PEXPIREAT 时间戳 来控制统一的过期事件


61、主从的一个小问题 protected-mode

如果设置 protected-mode yes 的话,哨兵只能被当前服务器的实例访问,会引发一系列的问题,建议设置为no,并且 bind 参数设置为主从节点的 ip


62、为什么脑裂导致了redis的部分数据丢失?

在脑裂的时候有服务还在连接原来的主库,哨兵集群判断主库下线,从库被选举为主库,而等 redis 原主库回复的时候,服务写在原服务里面的数据因为redis被变成 现主库的从库,要发生一次全量复制,导致期间产生的数据丢失。


63、如何应对脑裂问题?



  • min-slaves-to-write:设置了主库能进行数据同步最少的从库数量 N

  • min-slaves-max-lag:设置从库给主库发送ack消息的最大延迟 T

如果主库连接从库数量少于N,或主从数据复制时ack消息延迟超过T,则主库不会接收客户端发来的消息了


64、若从库能删数据,有什么风险??



  • 原本主库快要过期的 key 用 expire 续命了,但是因为有延迟,从库正好也删掉了,就会导致数据不一致

  • 主从库的时钟不同步,导致主从库删除时间不一致


65、如何理解把 Redis 称为旁路缓存?

业务应用在使用 Redis 缓存时,需要在业务代码中显式地增加缓存的操作逻辑。


66、秒杀支持



  • 前端静态页面的设计,秒杀页面能静态化的都要静态化,充分利用 CDN 与浏览器缓存

  • 请求拦截和流控,拦截恶意请求,为防止 Redis 流量过大,在接入层进行限流,如控制进入秒杀的数量

  • 库存信息过期时间处理,不给秒杀商品设置过期事件,防止击穿

  • 数据库订单异常处理,如果数据库没能处理成功,增加重试功能,保证订单能被最终处理

  • 秒杀数据单独保存,建议秒杀商品的信息用单独的实例去保存


67、数据倾斜是怎么产生的?



  • bigkey

  • Slot 分配不均衡,CLUSTER SLOTS 可查看 slot 的信息

  • Hash Tag


68、数据倾斜的解决方案

数据倾斜基本原因还是热点数据的问题,同长缓存还是读多一些,可以采用热点数据多副本的方式,把热点数据复制多份,在每个数据副本前增加一个前缀,这样热点数据的压力被分散到不同的实例上去了

此方法只针对 读热点数据


69、Redis cluster 集群通讯方式 gossip 是什么原理?



  • 集群中的会按照一定的频率选出一些实例,把ping命令发送给选出的实例,交换彼此的信息,ping中封装了发送消息的实例自身的状态信息、部分其他实例的状态信息,以及 slot 表

  • 一个实例接收到 ping 后,会发送 pong 给消息实例,包含的信息与 ping 一样

Gossip 协议可以保证在一段时间后,集群中的每一个实例都能获得其它所有实例的状态信息。



推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
author-avatar
Deenylou2010
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有