为什么

在传统的单体服务中,我们经常会遇到多线程对于单一资源的抢占导致的线程安全问题以及对数据库数据操作的一致性问题,如果是在单体系统中,我们可以很方便的使用编程语言提供的锁以及数据库事务来解决这些问题。

一旦单体系统转为分布式架构,那么本地事务和线程锁就无法满足跨进程的锁效果;分布式锁则是用于进程间同步访问共享资源的一种方式,通过全局共享来实现全局锁的效果,保证数据的一致性。

总的来说,在分布式系统中,当我们期望一个操作(一个请求、一个方法、一个数据库操作…)在整个系统中同一时间只能有一个线程执行,那我们就需要用到分布式锁; 抽象来看就是两个场景:

  • 单一资源的数据变更:比如对共享存储数据(数据库、缓存…)进行修改,多线程的互斥
  • access token:对于多个资源的原子性操作,期望整个业务逻辑就是单一线程执行保持一致性,在入口处就锁住

分布式锁应该具备的特性:

  • 原子性:在分布式系统中,一个方法在同一时间只能被一个线程执行
  • 阻塞性:在没获取到锁时可以进行阻塞也可以返回失败
  • 高可用:能够正确的获取锁和释放锁,且具备锁失效的能力
  • 高性能:获取锁与释放锁的性能保障
  • 可重入:能够具备可重入特性
阅读全文 »

Explain简介

本文主要讲述如何通过 explain 命令获取 select 语句的执行计划,通过 explain 我们可以知道以下信息:表的读取顺序,数据读取操作的类型,哪些索引可以使用,哪些索引实际使用了,表之间的引用,每张表有多少行被优化器查询等信息。

下面是使用 explain 的例子:

在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询时,会返回执行计划的信息,而不是执行这条SQL(如果 from 中包含子查询,仍会执行该子查询,将结果放入临时表中)。

mysql> explain select * from actor;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | actor | ALL | NULL | NULL | NULL | NULL | 2 | NULL |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+

在查询中的每个表会输出一行,如果有两个表通过 join 连接查询,那么会输出两行。表的意义相当广泛:可以是子查询、一个 union 结果等。

阅读全文 »

重装系统之后, 如果把原有的scoop文件夹粘贴回去user文件夹,然后在powershell中再次输入Windows下的软件管理神器:scoop文章中的安装命令,会得到一个Scoop is already installed错误,要想正确恢复scoop,根据官方回答,请按照以下步骤:

  1. 重装系统之前,先完整复制用户目录下的scoop文件夹到别的地方

  2. 重装系统之后,将scoop文件夹粘贴回去用户目录

  3. 在环境变量设置中,新建一个用户变量,名字为SCOOP,值为当前scoop文件夹的地址

    C:\Users\xxx\scoop
  4. 允许脚本执行

    set-executionpolicy remotesigned -s currentuser
  5. 双击用户变量中的path,新建一个路径,填入

    %SCOOP%\shims
  6. 管理员权限powershell中运行

    scoop reset *
  7. 即可恢复所有软件的正常使用

原文地址

什么是内存碎片?

你可以将内存碎片简单地理解为那些不可用的空闲内存。

举个例子:操作系统为你分配了 32 字节的连续内存空间,而你存储数据实际只需要使用 24 字节内存空间,那这多余出来的 8 字节内存空间如果后续没办法再被分配存储其他数据的话,就可以被称为内存碎片。

内存碎片

Redis 内存碎片虽然不会影响 Redis 性能,但是会增加内存消耗。

阅读全文 »

性能状态关键指标

  • QPS,Queries Per Second:每秒查询数,一台数据库每秒能够处理的查询次数

  • TPS,Transactions Per Second:每秒处理事务数

  • Uptime:服务器已经运行的实际,单位秒

  • Questions:已经发送给数据库查询数

  • Com_select:查询次数,实际操作数据库的

  • Com_insert:插入次数

  • Com_delete:删除次数

  • Com_update:更新次数

  • Com_commit:事务次数

  • Com_rollback:回滚次数

-- 58228968
show global status like 'Questions';

-- 55155
show global status like 'Uptime';

-- QPS = Questions / Uptime
-- 1055 = 58228968 / 55155

-- 7689868
show global status like 'Com_commit';

-- 7737499
show global status like 'Com_rollback';

-- TPS = (Com_commit + Com_rollback) / Uptime
-- 280 = ( 7689868 + 7737499 ) / 55155

-- Com_delete 609
-- Com_insert 30627
-- Com_select 23580917
-- Com_update 3549397
show global status where Variable_name in('com_select','com_insert','com_delete','com_update');
SELECT SLEEP(1);
-- Com_delete 609
-- Com_insert 30629
-- Com_select 23583220
-- Com_update 3549478
show global status where Variable_name in('com_select','com_insert','com_delete','com_update');

-- ( (609 - 609) + (30629 - 30627) + (3549478 - 3549397) ) = 83
-- ( 23583220 - 23580917 ) = 2303