October 25, 2019
MySQL8.0中的跳跃范围扫描优化Skip Scan Range Access Method介绍
"在MySQL8.0以前,索引使用规则有一项是索引左前缀,假如说有一个索引idx_abc(a,b,c),能用到索引的情况只有查询条件为a、ab、abc、ac这四种,对于只有字段b的where条件是无法用到这个idx_abcf索引的。这里再强调一下,这里的顺序并不是在where中字段出现的顺序,where b=2 and 1=1 也是可以利用到索引的,只是用到了(a,b)这两个字段\n针对这一点, 从MySQL 8.0.13开始引入了一种新的优化方案,叫做 Skip Scan Range,翻译过来的话是跳跃范围扫描。如何理解这个概念呢?我们可以拿官方的SQL示例具体讲一下()\nCREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL, PRIMARY KEY(f1, f2)); INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (2,2), (2,3), (2,4), (2,5); INSERT INTO t1 SELECT f1, f2 + 5 FROM t1; …"
October 18, 2019
一致性哈希算法及其在分布式系统中的应用(推荐)
"摘要 本文将会从实际应用场景出发,介绍一致性哈希算法(Consistent Hashing)及其在分布式系统中的应用。首先本文会描述一个在日常开发中经常会遇到的问题场景,借此介绍一致性哈希算法以及这个算法如何解决此问题;接下来会对这个算法进行相对详细的描述,并讨论一些如虚拟节点等与此算法应用相关的话题。\n分布式缓存问题 假设我们有一个网站,最近发现随着流量增加,服务器压力越来越大,之前直接读写数据库的方式不太给力了,于是我们想引入Memcached作为缓存机制。现在我们一共有三台机器可以作为Memcached服务器,如下图所示。\n很显然,最简单的策略是将每一次Memcached请求随机发送到一台Memcached服务器,但是这种策略可能会带来两个问题:一是同一份数据可能被存在不同的机器上而造成数据冗余,二是有可能某数据已经被缓存但是访问却没有命中,因为无法保证对相同key的所有访问都被发送到相同的服务器。因此,随机策略无论是时间效率还是空间效率都非常不好。\n要解决上述问题只需做到如下一点:保证对相同key的访问会被发送到相同的服务器。很多方法可以实现这一点,最常用的方法是计算哈希。例如 …"
August 31, 2019
Redis 选择hash还是string 存储数据?
"在Redis中存储数据时,经常使用string和hash这两种类型,至于这两者有什么不同,底层实现有何区别,推荐参考: https://segmentfault.com/a/1190000019552836"
August 13, 2019
一文理解MySQL中的page页
"在介绍InnoDB中的页的时候,很有必要先让大家了解一下InnoDB中的存储结构\n从InnoDB存储引擎的逻辑结构看,所有数据都被逻辑地存放在一个空间内,称为表空间(tablespace),而表空间由段(sengment)、区(extent)、页(page)组成。 在一些文档中extend又称块(block)。\n一、表空间(table space)\n表空间(Tablespace)是一个逻辑容器,表空间存储的对象是段,在一个表空间中可以有一个或多个段,但是一个段只能属于一个表空间。数据库由一个或多个表空间组成,表空间从管理上可以划分为系统表空间、用户表空间、撤销表空间、临时表空间等。\n在 InnoDB 中存在两种表空间的类型:共享表空间和独立表空间。如果是共享表空间就意味着多张表共用一个表空间。如果是独立表空间,就意味着每张表有一个独立的表空间,也就是数据和索引信息都会保存在自己的表空间中。独立的表空间可以在不同的数据库之间进行迁移。可通过命令\nmysql \u0026gt; show variables like \u0026#39;innodb_file_per_table\u0026#39;; 查看当前系统启用 …"
August 12, 2019
一列说明数组与Hash效率的区别到底多大
"在数组中添加 10000 个元素,然后分别对这 10000 个元素进行检索,最后统计检索的时间。\n数组Array\nimport time # 插入数据,数组 result = [] for i in range(10000): result.append(i) # 检索数据 time_start=time.time() for i in range(10000): temp = result.index(i) time_end=time.time() print(\u0026#39;检索时间\u0026#39;, time_end-time_start) 运行结果:\n检索时间为 1.2436728477478027 秒。\nHash哈希\nimport time # 插入数据 result = {} for i in range(1000000): result[i] = i # 检索数据 time_start=time.time() for i in range(10000): temp = result[i] time_end=time.time() print(\u0026#39;检索时 …"
July 29, 2019
kubernetes dashboard向外网提供服务
"目前新版本的 kubernetes dashboard ()安装了后,为了安全起见,默认情况下已经不向外提供服务,只能通过 http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ 本机访问。在我们学习过程中,总有些不方便,这时我们可以利用 kubectl proxy 命令来实现。\n首先我们看一下此命令的一些想着参数\n➜ ~ kubectl proxy -h To proxy all of the kubernetes api and nothing else, use: $ kubectl proxy --api-prefix=/ To proxy only part of the kubernetes api and also some static files: $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/ The above lets you …"
July 28, 2019
RabbitMQ常见面试题
"RabbitMq的消息类型(6种)、 消息确认机制\nRabbitMq中的概念及解释\nServer(Broker): 接收客户端连接,实现AMQP协议的消息队列和路由功能的进程; Virtual Host:虚拟主机的概念,类似权限控制组,一个Virtual Host里可以有多个Exchange和Queue。 Exchange: 交换机,接收生产者发送的消息,并根据Routing Key将消息路由到服务器中的队列Queue。 ExchangeType: 交换机类型决定了路由消息行为,RabbitMQ中有四种类型Exchange,分别是fanout、direct、topic 和 headers; Queue:消息队列,用于存储还未被消费者消费的消息; Message:由Header和body组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、优先级是多少、由哪个Message Queue接收等;body是真正需要发送的数据内容; BindingKey:绑定关键字,将一个特定的 Exchange 和一个特定的 Queue 绑定起来。 2.对mq有哪些理 …"
July 28, 2019
rabbitmq消息队列的消息持久化机制
"首先阅读这篇文章: https://blog.csdn.net/yongche_shi/article/details/51500534\n之前其实已经写过一篇关于RabbitMQ持久化的 文章 ,但那篇文章侧重代码层面的写入流程,对于持久化操作何时发生以及什么时候会刷新到磁盘等问题其实都没有搞清楚,这篇文章着重于关注这些问题。\n消息什么时候需要持久化? 根据 官方博文 的介绍,RabbitMQ在两种情况下会将消息写入磁盘:\n消息本身在 publish 的时候就要求消息写入磁盘; 内存紧张 需要将部分内存中的消息转移到磁盘; 消息什么时候会刷到磁盘? 写入文件前会有一个Buffer,大小为1M(1048576),数据在写入文件时,首先会写入到这个Buffer,如果Buffer已满,则会将Buffer写入到文件(未必刷到磁盘); 有个固定的刷盘时间:25ms,也就是不管Buffer满不满,每隔25ms,Buffer里的数据及未刷新到磁盘的文件内容必定会刷到磁盘; 每次消息写入后,如果没有后续写入请求,则会直接将已写入的消息刷到磁盘:使用Erlang的receive x after 0来实 …"
July 26, 2019
docker exec 命令原理
"我们经常使用 docker exec 命令进入到一个容器里进行一些操作,那么这个命令是如果进入到容器里的呢?想必大家都知道用到了Namespace来实现,但至于底层实现原理是什么,想必都不是特别清楚吧。\n我们知道容器的本质其实就是一个进程,每个进程都有一个Pid,至于容器的Pid值可以通过 docker inspect container_id 来查看,我们这里是一个Python应用容器,我们看一下他的 Pid值\ndocker inspect --format \u0026#39;{{ .State.Pid }}\u0026#39; 4ddf4638572d 25686 而每个进程都有自己的Namespace,你可以通过查看宿主机的 proc 文件,看到这个 25686 进程的所有 Namespace 对应的文件\nls -l /proc/25686/ns total 0 lrwxrwxrwx 1 root root 0 Aug 13 14:05 cgroup -\u0026gt; cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Aug 13 14:05 ipc -\u0026gt; …"
July 26, 2019
docker中的命名空间
"Namespace 的作用是“隔离”,它让应用进程只能看到该Namespace 内的“世界”;而 Cgroups 的作用是“限制”,它给这个“世界”围上了一圈看不见的墙。\n命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样。命名空间保证了容器之间彼此互不影响。\n在docker中一共有以下几个命名空间,每个Namespace的发挥着不同的作用。\npid 命名空间 不同用户的进程就是通过 pid 命名空间隔离开的,且不同命名空间中可以有相同 pid。在同一个Namespace中只能看到当前命名空间的进程。所有的 LXC 进程在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的命名空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。\nnet 命名空间 有了 pid 命名空间, 每个命名空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 命名空间实现的, 每个 net 命名空间有独立的 网络设备, IP 地址, 路由表, …"