mysqlcrud语句
MySQL的基本操作可以包括两个方面:MySQL常用语句如高频率使用的增删改查(CRUD)语句和MySQL高级功能,如存储过程,触发器,事务处理等。而这两个方面又可以细分如下:MySQL常用语句表(或...
2024.11.15在安装的redis/src文件夹下可以看到有很多后缀名为.h、.c、.o的文件,其中.h代表的是.c文件中用到的变量、数组、函数的声明,.c文件是.h文件中声明的变量、数组、函数具体的定义,而.o就是编译后的汇编文件。
大家可以看到有dict.h文件,这个文件里面即定义了字典的数据结构,我们打开源码可以看到如下四个C语言的结构体(struct):
typedef struct dictEntry {void *key;union {void *val;uint64_t u64;int64_t s64;double d;} v;struct dictEntry *next;} dictEntry;typedef struct dictType {uint64_t (*hashFunction)(const void *key);void *(*keyDup)(void *privdata, const void *key);void *(*valDup)(void *privdata, const void *obj);int (*keyCompare)(void *privdata, const void *key1, const void *key2);void (*keyDestructor)(void *privdata, void *key);void (*valDestructor)(void *privdata, void *obj);} dictType;typedef struct dictht {dictEntry **table;unsigned long size;unsigned long sizemask;unsigned long used;} dictht;typedef struct dict {dictType *type;void *privdata;dictht ht[2];long rehashidx; /* rehashing not in progress if rehashidx == -1 */unsigned long iterators; /* number of iterators currently running */} dict;用一张图来表述他们之间的关系如下:
当我们执行一条如下语句的时候:
set testKey testValue如果是首次redis写入,会创建一个dict字典对象,字典对象的数据如下:
当然如果你写入的不是字符串类型的数据类型,而是List、Hash、Set、ZSet四种数据,也和上图的数据结构一样,只是dictEntry里面的值对象*val指针会指向不同的对象,不同的对象会有不同的数据结构,强烈推荐大家阅读《redis设计与实现》这本书,深读此书将会彻底搞清楚redis。
redis内存计算上节从redis的字典说了redis的底层数据结构是如何保存我们写入的key的,那么当我们执行命令写入key到redis中,redis的内存具体是如何分配的呢?我们一起来实验一下:
首先执行FLUSHALL命令来清空我们的redis,保证没有其他key干扰,然后执行:
src/redis-cli info | grep mem获取redis初始内存信息:
关键属性说明如下(更多属性说明请查阅redis官网):
redis初始占用内存:1039472字节,当我们执行:
set testKey testValue再查看内存变化为:
也就是说上面的语句执行后吃了redis内存为:1057472-1039472=18000b=17.58K,那是不是代表上面的执行吃了18K的内存呢?
我们再写入一个key:
set testKey1 testValue1通过上文对字典的描述可以知道testKey1在redis中的存储应该如下图所示:
查看内存变化为:
used_memory:1057552
才发现吃了80字节的内存。
所以我们可以知道的是redis启动之后需要占用一部分内存,这部分内存1039472字节用于redis服务的运行以及初始化一些数据。另外首次写入redis的key之后,需要构造上文所说的redis字典结构,因此需要占用一些内存。
我们需要知道的是当我们写入一个key的时候占用的内存到底是多少,由于我们写的值都没有超过44个字节,所以采用EMBSTR数据结构存储。所以我们可以查看object.c源码里面是如何创建对象的:
分配内存的代码:
robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1);可以看到redis为我们分配了:
sizeof(robj)+sizeof(struct sdshdr8)+len+1这么大的内存,其中的robj代表的是redisObject,查看server.h中关于redisObject对象的定义:
因此sizeof(robj) = 16字节。
sdshdr8即上图中的sdshdr中的头部3个字节。
因此testValue1这个采用EMBSTR编码的存储需要内存:16+3+10+1=30字节,redis内存分配器为其分配32字节。
我们再来计算testKey1占用的内存,testKey1存储的就是一个SDS简单动态对象,少了robj的内存占用,因此需要内存:3+8+1 = 12字节,redis分配器为其分配16字节。
总共需要内存为32+16=48字节,那为什么占用的是80字节呢?剩下的32字节谁吃了呢?大家不要忘记了dictEntry这个结构还有三个指针呢:
三个指针占用内存:3*8-24字节,jemalloc会为其分配32个字节。
至此,我们便能清晰的知道当我们执行一个字符串对象(字符串长度不超过44!)写入的时候,需要占用内存多少了。
即80-18(testKey1&testValue1) = 62的长度。但是我们需要知道这62个长度都吃在什么地方了。
上面说的是当写入String类型的数据且长度值不超过44的时候占用的内存计算方法。其他数据类型如List、Hash、Set、Zset大家可以参考我上面的方法和思路并查看相关redis源码以及redis技术资料即可得知。
redis-benchmark压测src目录下redis-benchmark是redis自带的压测工具,压测语法格式:
redis-benchmark [option] [option value]option可选参数如下:
执行压测语句:
src/redis-benchmark -p 6379 -t set -c 100 -n 1000000 -r 1000000输出压测结果:
➜redis-5.0.7 src/redis-benchmark -p 6379 -t set -c 100 -n 1000000 -r 1000000====== SET ======1000000 requests completed in 20.04 seconds100 parallel clients3 bytes payloadkeep alive: 144.04%MySQL的基本操作可以包括两个方面:MySQL常用语句如高频率使用的增删改查(CRUD)语句和MySQL高级功能,如存储过程,触发器,事务处理等。而这两个方面又可以细分如下:MySQL常用语句表(或...
2024.11.15说明Web应用程序,MySQL数据库,数据库中有三张表:health_patient(病人表)、health_patient_account(病人账户表)、health_patient_medical...
2024.11.12在并发控制编程中锁是一个非常重要的概念,锁对于数据和业务一致性的保证起到关键作用,锁可以是程序层面的,也可以是数据库层面的,今天本文就通过MySQL来说明悲观锁与乐观锁两种常见的锁机制。悲观锁悲观锁(...
2024.11.15MySQL 事务主要用于处理操作量大,复杂度高的数据。MySQL事务表(TST)支持将多条SQL语句当作同一任务统一处理,要么此任务所有SQL语句统一提交,要么全部被撤销回滚;而非事务表(NTST)则...
2024.11.15概述从zabbix监控发现某台数据库服务器经常发生内存告警,使用率达到95%,下面从连接数角度来分析一下该数据库服务器内存占用过高问题..1、查看数据库分配内存大小( mysql内存计算器,具体地址为...
2024.11.15