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

Java面试——Redis相关

Redis底层数据结构字符串底层存储在Redis中,字符串有三种存储编码方式:int编码、embstr编码和raw编码int编码当value是一个

Redis 底层数据结构


字符串底层存储

在Redis 中,字符串有三种存储编码方式: int编码 、embstr编码和raw编码

int编码
当value是一个整数且值大小不超过8个字节,就会是哟红int编码,ptr直接存储数值

embstr 编码

embstr对象用于存储比较短的字符串,embstr编码中RedisObject结构与ptr指向的SDS 结构在内存中是连续的,内存分配次数和内存释放次数均是一次。
raw编码会分别调用两次内存分配函数来分别创建RedisObject结构个SDS结构。


hash对象

Redis中,hash类型的value可以是一个hash表,底层编码可以是ziplist,也可以是hashtable。
默认情况下,当元素个数小于512个时,底层使用ziplist存储数据。

ziplist
元素保存的字符串长度较短且元素个数较少。(长度小于64字节,个数小于512),出于节约内存考虑,hash表会使用ziplist作为底层实现,ziplist是一块连续的内存,里面每一个节点保存了对应的key和value,然后每个节点很紧凑地存储在一起。
优点是: 没有冗余空间
缺点是: 插入新元素需要调用realloc扩展内存,这可能会导致内存重分配

hashtable

元素比较多是就会使用hashtable编码作为底层实现。此时RedisObject的ptr指针指向一个dict结构,dict结构中的ht数组有两个元素h[0]和h[1]。通常h[0]保存键值对,h[1]只在渐进式rehash时使用,hashtable是通过链地址法来解决冲突的。


Zset

Zset在存储时会将元素按照score从低到高排列,底层是通过跳表实现的。

ziplist
当元素较少时(元素长度小于64字节,且元素个数小于128),Zset的底层编码使用ziplist实现,所有元素按照score从低到高排序。

skiplist + dict
当元素较多时,使用skiplist + dict来实现。skiplist存储元素的值和score,并且将所有元素按照分值有序排列。便于以O(logN)的时间复杂度插入,删除,更新,及根据Score进行范围性查找。

dict存储元素的值和Score的映射关系,便于以O(1)的时间复杂度查找元素对应的分值。


跳表

跳表就是层次化的链表结构,它由多个链表组成。只有底层的链表保存节点数据,一般来说每两个节点选出一个节点作为下一级索引的节点,让下一级 索引的节点数量为本机索引节点数量的一半。依次类推直至最顶层索引节点数为1。
原理是每次查找数据时,先在最上层查找,然后再定位到下一层,层层定位,直至最终找到目标数据。这种方式不用遍历整个链表,而是跳跃着差,这样就使得查找时间复杂度退化到了logn


为什么不使用List、红黑树或平衡二叉树呢?

List是顺序㽾,访问速度很快,但是添加和删除操作是O(N)操作。至于红黑树和平衡二叉树,每次更新redis的值,都要消耗O(logn)的复杂度调整树结构,而跳跃表只需要调整局部链表结构就行,显然跳跃表更适合。
跳跃表支持平均O(logN)、最坏O(N)的复杂度进行节点查找,还可以通过顺序性操作来批量处理节点。
在大部分情况下,跳跃表的效率与平衡树媲美,但是跳跃表的实现要比平衡树要来得更为简单。

Redis 常用数据结构底层实现


缓存雪崩


重复排队、并发超卖、数据不一致


redis分布式锁


  1. 单机多线程下存在并发问题。 – 在JVM层面加锁,如synchronized或ReentrantLock
  2. 分布式部署下存在超卖问题。 --使用Redis分布式锁,加解锁。

String value = UUID.random().toString();
Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value); //加锁
stringRedisTemplate.delte(REDIS_LOCK)



  1. 秒杀业务逻辑代码块出现异常时可能无法释放掉锁。 — 增加try -catch 语句块 在finally代码块释放锁
  2. 部署了秒杀服务的服务器宕机 – 对lockkey 增加过期时间的设定
    在这里插入图片描述5. 原子性考虑。 加锁和设置过期时间非原子操作
    在这里插入图片描述

EX seconds – Set the specified expire time, in seconds.
PX milliseconds – Set the specified expire time, in milliseconds.


  1. 误删其他事务的锁。 必须在删除锁之前判断是否是自己的加的锁。
    在这里插入图片描述
    在这里插入图片描述
  2. 判断是否是自己加的锁 与 解锁非原子性操作,那么会出现判断加锁与解锁不是同一个客户端导致误解锁

在这里插入图片描述


  • 利用LUA脚本
    在这里插入图片描述

  • 使用Redis的事务

在这里插入图片描述

仍然存在 redisLock 过期时间小于业务执行时间的问题,也就是如何实现分布式锁的续期问题。
再者在集群环境下还存在Redis的主从不一致

Redison
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


  1. 在超高并发下,可能出现IllegalMonitorStateException

在这里插入图片描述

在这里插入图片描述

select … for update后,对所在行加了互斥锁,而你使用select …在Innodb里是快照读,是不涉及到锁的问题的,如果想要验证加锁是否成功,需要对查询加共享锁 lock in share mode或互斥锁for update

注意需要两个会话都开启事务:


select * from tmp_file_bk limit 0,10 for update;


之后会话2,使用


select * from tmp_file_bk where id = 106 lock in share mode ;


也无法访问到


推荐阅读
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
author-avatar
江韦亭君733
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有