- 博客(23)
- 收藏
- 关注
原创 10.MC是怎么定位key以及如何淘汰冷key和失效key的
key定位哈希表Mc 将数据存储在 Item 中,然后这些 Item 会被 slabclass 的 4 个 LRU 管理。这些 LRU 都是通过双向链表实现数据记录的。双向链表在进行增加、删除、修改位置时都非常高效,但其获取定位 key 的性能非常低下,只能通过链表遍历来实现。因此,Mc 还通过 Hashtable,也就是哈希表,来记录管理这些 Item,通过对 key 进行哈希计算,从而快速定位和读取这些 key/value 所在的 Item,如下图所示。哈希表也称散列表,可以通过把 key 映射
2020-09-16 14:29:12
708
原创 09.MC是如何使用多线程和状态机来处理请求命令的
网络模型主线程Mc 基于 Libevent 实现多线程网络 IO 模型。Mc 的 IO 处理线程分主线程和工作线程,每个线程各有一个 event_base,来监听网络事件。主线程负责监听及建立连接。工作线程负责对建立的连接进行网络 IO 读取、命令解析、处理及响应。Mc 主线程在监听端口时,当有连接到来,主线程 accept 该连接,并将连接调度给工作线程。调度处理逻辑,主线程先将 fd 封装成一个 CQ_ITEM 结构,并存入新连接队列中,然后轮询一个工作线程,并通过管道向该工作线程发送通知。工作线
2020-09-14 16:29:25
922
原创 08.MC系统架构是如何布局的
系统架构如下图所示,Mc 的系统架构主要包括网络处理模块、多线程处理模块、哈希表、LRU、slab 内存分配模块5部分。Mc 基于 Libevent 实现了网络处理模块,通过多线程并发处理用户请求;基于哈希表对 key 进行快速定位,基于 LRU 来管理冷数据的剔除淘汰,基于 slab 机制进行快速的内存分配及存储。系统架构Mc 基于 Libevent 开发实现了多线程网络模型。Mc 的多线程网络模型分为主线程、工作线程。这些线程通过多路复用 IO 来进行网络 IO 接入以及读写处理。在 Linux
2020-09-09 15:19:24
1781
原创 07.MC为何是应用最广泛的缓存组件
Memcached 原理及特性原理Memcached 是一个开源的、高性能的分布式 key/value 内存缓存系统。它以 key/value 键值对的方式存储数据,是一个键值类型的 NoSQL 组件。NoSQL 即 Not SQL,泛指非关系类型数据存储。NoSQL 是通过聚合模型来进行数据处理的。其聚合模型主要分为:key/value 键值对、列族、图形等几种方式。其中 key/value 键值类似我们平常使用的 map,只通过 key 来进行查询和变更操作。我们使用的 Memcached、Red
2020-09-02 23:32:11
448
原创 06.Hot Key 和 Big Key 引发的问题怎么应对
Hot Key问题描述对于大多数互联网系统,数据是分冷热的。比如最近新闻、新发表的微博被访问的频率最高,而比较久远的之前的新闻、微博被访问的频率就会小很多。而在突发事件发生时,大量用户同时去访问这个突发热点信息,访问这个 Hot key,这个突发热点信息所在的缓存节点就很容易出现过载和卡顿现象,甚至会被 Crash。原因分析Hot key 引发缓存系统异常,主要是因为突发热门事件发生时,超大量的请求访问热点事件对应的 key,比如微博中数十万、数百万的用户同时去吃一个新瓜。数十万的访问请求同一个 k
2020-08-30 11:40:39
320
原创 05.缓存数据不一致和并发竞争怎么处理
数据不一致问题描述同一份数据,可能会同时存在 DB 和缓存之中。那就有可能发生,DB 和缓存的数据不一致。如果缓存有多个副本,多个缓存副本里的数据也有可能会发生不一致现象。原因分析不一致的问题大多跟缓存更新异常有关。比如更新 DB 后,写缓存失败,从而导致缓存中存的是老数据。另外,如果系统采用一致性 Hash 分布,同时采用 rehash 自动漂移策略,在节点多次上下线之后,也会产生脏数据。缓存有多个副本时,更新某个副本失败,也会导致这个副本的数据是老数据。业务场景导致数据不一致的场景也不少。如
2020-08-30 10:43:02
644
原创 04.缓存失效、穿透和雪崩问题怎么处理
缓存失效问题描述服务系统查数据,首先会先查缓存,如果缓存数据不存在,就进一步查 DB,最后查到数据回种到缓存并返回。缓存的性能比 DB 高 50~100 倍以上,所以我们希望数据查询尽可能命中缓存,这样系统负荷最小,性能最佳。缓存里的数据存储基本都是以 key 为索引进行存储和获取的。业务访问时,如果大量的 key 同时过期,很多缓存数据访问都会 miss,进而穿透到 DB,DB 的压力就会明显上升,由于 DB 的性能较差,只在缓存的 1% ~ 2% 以下,这样请求的查询效率会明显下降,这就是缓存失效的
2020-08-20 20:25:59
259
原创 SpringBoot整合SpringSecurity以后如何解决跨域问题
什么是跨域问题.跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript 施加的安全限制。什么是同源所谓同源是指 域名、协议、端口均相同http://www.abc.com --> http://test.abc.com 跨域http://www.abc.com --> http://www.abc.com 非跨域http://www.abc.com --> http://www.abc.com:8080 跨域https://w
2020-08-19 15:13:21
1633
原创 整合SpringSecurity和JWT实现认证和授权(2)
登录注册功能实现添加UmsAdminController类实现用户登录、注册及获取权限的接口@Controller@Api(tags = "UmsAdminController", description = "后台用户管理")@RequestMapping("/admin")public class UmsAdminController { @Autowired private UmsAdminService adminService; @Value("${jwt.to
2020-08-18 15:59:48
273
原创 Java8 Stream API
Java 8 引入了全新的 Stream API,可以使用声明的方式来处理数据,极大地方便了集合操作,让我们可以使用更少的代码来实现更为复杂的逻辑,本文主要对一些常用的Stream API进行介绍。
2020-08-15 11:49:32
186
原创 整合SpringSecurity和JWT实现认证和授权(1)
通过整合SpringSecurity和JWT实现后台用户的登录和授权功能,同时改造Swagger-UI的配置使其可以自动记住登录令牌进行发送。
2020-08-14 19:30:58
396
原创 03.缓存的引入及架构设计
缓存组件选择在设计架构缓存时,首先要选定缓存组件,比如要用 Local-Cache,还是 Redis、Memcached、Pika 等开源缓存组件,如果业务缓存需求比较特殊,还要考虑是否直接定制开发一个新的缓存组件,还是对开源缓存进行二次开发,来满足业务需要。缓存数据结构设计确定好缓存组件后,还要根据业务访问的特点,进行缓存数据结构的设计。对于简单 KV 读写的业务,可以将这些业务数据封装为 String、Json、Protocol Buffer 等格式,序列化成字节序列,然后直接写入缓存中。读取时,
2020-08-10 22:44:57
178
原创 02.缓存的读写模式以及缓存的分类
缓存的读写模式缓存有三种读写模式:Cache Aside(旁路缓存)Read/Write Through(读写穿透)Write Bechind Caching(异步缓存写入)Cache Aside如上图所示,Cache Aside 模式中,业务应用方对于写,是更新 DB 之后,直接将 key 从 cache 中删除,然后由 DB 驱动缓存数据的更新;而对于读,是先读 cache,如果 cache 没有,则读 DB ,同时将从 DB中读取的数据回写到 cache。这种模式的特点是,业务端
2020-08-09 15:58:09
591
1
原创 深入浅出JVM(7)
经过前面的分析学习,直到了关于JVM很多知识,比如版本信息,类加载器,堆,方法区,垃圾回收等,接下来我们来看看怎么将这些内容直观地展示在我们面前,包括怎么进行相应的一些设置。JVM参数标准参数-version-help-server-cp-X参数非标准参数,也就是在JDK各个版本中可能会变动-Xint 解释执行-Xcomp 第一次使用就编译成本地代码-Xmixed 混合模式,JVM自己来决定-XX参数使用得最多的参数类型。非标准化参数,相对不稳定.
2020-08-02 18:22:58
209
原创 01.缓存的原理
缓存的定义缓存最初的含义,是指用于加速CPU数据交换的RAM,及随机存取存储器,通常这种存储器使用更昂贵但快速的静态RAM(SARAM)技术,用以对DRAM进行加速。这是一个狭义缓存的定义。而广义缓存的定义则更宽广,任何可以用于数据高速交换的存储介质都是缓存,可以是硬件也可以是软件。缓存存在的意义就是通过开辟一个新的数据交换缓冲区,来解决原始数据获取代价太大的问题,让数据得到更快的访问。缓存原理缓存的基本思想缓存构建的基本思想是利用时间局限性原理,通过空间换时间来达到加速数据获取的目的,
2020-08-02 00:13:54
294
原创 深入浅出JVM(6)
垃圾收集器如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。SerialSerial收集器是最基本、发展历史最悠久的收集器,曾经(在JDK1.3.1之前)是虚拟机新生代收集的唯一选择。它是一种单线程收集器,不仅仅意味着它只会使用一个CPU或者一条收集线程去完成垃圾收集工作,更重要的是其在进行垃圾收集的时候需要暂停其他线程。优点:简单高效,拥有很高的单线程收集效率缺点:收集过程需要暂停所有线程算法:复制算法适用范围:新生代应用:Client模式下的默认新生代收集器
2020-06-14 12:11:14
280
原创 深入浅出JVM(5)
Garbage Collect(垃圾回收)之前说堆内存中有垃圾回收,比如Young区的Minor GC,Old区的Major GC,Young区和Old区的Full GC。但是对于一个对象而言,怎么确定它是垃圾?是否需要被回收?怎样对它进行回收?等等这些问题我们还需要详细探索。因为Java是自动做内存管理和垃圾回收的,如果不了解垃圾回收的各方面知识,一旦出现问题我们很难进行排查和解决,自动垃圾回收机制就是寻找Java堆中的对象,并对对象进行分类判别,寻找出正在使用的对象和已经不会使用的对象,然后把那
2020-06-14 11:00:21
300
原创 深入浅出JVM(4)
JVM内存模型jvm的内存模型其实就是上一篇文章所讲述的运行时数据区,这里就不在过多的阐述了。重点存储数据的是堆和方法区(非堆),所以内存的设计也着重从这两方面展开(注意这两块区域都是线程共享的,对于虚拟机栈,本地方法栈,程序计数器都是线程私有的)。可以这样理解,JVM运行时数据区是一种规范,而JVM内存模式是对该规范的实现堆与非堆图形展示一块是非堆区,一块是堆区堆区分为两大块,一个是Old区,一个是Young区Young区分为两大块,一个是Survivor区(S0+S1),一块是Eden区
2020-06-14 10:31:03
270
原创 深入浅出JVM(3)
运行时数据区官网概括:The Java Virtual Machine defines various run-time data areas that are used during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only when the Java Virtual Machine exits. Other
2020-06-13 23:25:46
125
原创 深入浅出JVM(2)
类文件到虚拟机(类加载机制)加载机制虚拟机把class文件加载到内存,并对数据进行校验,转换解析和初始化,形成虚拟机可以直接使用的java类型,即java.lang.Class1. 装载(Load)查找和导入class文件(1)通过一个类的全限定名获取定义此类的二进制字节流;(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;(3)在java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。Class对象封装了类在方法区内的数据结
2020-06-13 16:51:38
124
原创 深入浅出JVM(1)
本文基于jdk1.8和官方文档进行阐述,有兴趣的可以到官网上看看<https://docs.oracle.com/javase/8/>
2020-06-13 11:16:35
175
原创 关于线程的一些知识整理(2)
线程池线程池是为了避免线程频繁的创建和销毁带来的性能消耗,而建立的一种池化技术,它是把已创建的线程放入“池”中,当有任务来临时就可以重用已有的线程,无需等待创建的过程,这样就可以有效提高程序的响应速度。线程池的创建newFixedThreadPool:创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池补充一个新的线程。适用于任务数量不均匀的场景、对内存压力不敏感但系统负载比较敏感的场景。newCached
2020-05-21 14:56:40
118
原创 关于线程的一些知识整理(1)
线程的创建①. 继承Thread类创建线程类定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。创建Thread子类的实例,即创建了线程对象。调用线程对象的start()方法来启动该线程。②. 通过Runnable接口创建线程类定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。创建 Runnable实现类的实例,并依此实例作为Thread的target来创建
2020-05-21 14:34:17
112
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人