PostgreSQL

PostgreSQL commands \l 或 \list meta-command 列出所有数据库 sudo -u postgres psql -c "\l" 用 \c + 数据库名 来进入数据库: \dt 列出所有数据库表: # 查看表结构, 索引 \d table0 # 比上面多几个字段 Storage | Stats target | Description \d+ table0 # Turn off printing of column names and result row count footers, etc. This is equivalent to \t or \pset tuples_only. \t tuples only on/off, tuples only on 的时候 select 语句的输出不带 header \h \? \du 列出所有的用户 # 创建用户 CREATE USER user_0 WITH PASSWORD 'password_0'; # create database, 所有者 user_0 create database database_0 OWNER user_0; psql -h 192.168.1.100 -p 5432 -U user_0 -d database_0 PGPASSWORD=password_0 psql -h 192.168.1.100 -p 5432 -U user_0 -d database_0 --command 'select version();' #当表没有其他关系时 TRUNCATE TABLE tablename; #当表中有外键时,要用级联方式删所有关联的数据 TRUNCATE TABLE tablename CASCADE; # 查看 表大小 select pg_size_pretty(pg_relation_size('table0')); # 查看配置文件路径, 切换到 postgres 用户执行 psql -c "show config_file" # 查看版本 select version(); pacman -S postgresql psql -h 127.0.0.1 -p 5432 -d database0 -U user0 # create table create table test(id int, c1 int); create table table0(field0 json); # delete table DROP TABLE table0; # 查看字段类型 select column_name, data_type from information_schema.columns where table_name='table0'; select * length( "abc"::TEXT) insert into test select generate_series(1,10000), random()*10; # 复制表结构到另外一个数据库 pg_dump -U postgres --schema-only source_db | psql -U postgres target_db 导入/导出 export, 导出, 备份 # https://www.postgresql.org/download/linux/ubuntu/ # install pg_dump sudo apt install -y postgresql-common # This script will enable the PostgreSQL APT repository on apt.postgresql.org sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh # ubuntu install pg_dump sudo apt-get install postgresql-client-17 # -h, host 127.0.0.1 # -p, port 5432 # -t, table: table0, 不加 -t 参数时会导出所有表结构 # -s, 不导出数据 # database: database0 # -F : 指定输出文件的格式,它可以是以下格式之一: c: 自定义格式 d: 目录格式存档 t: tar 文件包 p: SQL 脚本文件 # -W 命令执行时提示输入用户密码(不会直接在命令中写密码)。 pg_dump -h 127.0.0.1 -U username -W -F t db_name > foo.tar # 导入 # -c --clean 创建数据库对象前先清理(删除)它们。 pg_restore -h 127.0.0.1 -U username -W -d db_name -c foo.tar pg_dump -h 127.0.0.1 -p 5432 -t table_0 -U postgres database0 > foo.sql pg_dump -h 127.0.0.1 -p 5432 -s -t table_0 -U postgres database0 > foo.sql # 导出并压缩 pg_dump -d db_name | gzip > db.gz pg_dump -a -t table_0 "host=127.0.0.1 hostaddr=127.0.0.1 port=5432 user=user_0 password=password_0 dbname=db_0" # export insert sql pg_dump -a -t table_0 "host=127.0.0.1 hostaddr=127.0.0.1 port=5432 user=user_0 password=password_0 dbname=db_0" --inserts 导入 # sql psql -h 127.0.0.1 -p 5432 -t table0 -U postgres -d database0 -f foo.sql # csv, https://stackoverflow.com/questions/26701735/extra-data-after-last-expected-column-while-trying-to-import-a-csv-file-into-p \COPY agency (agency_name, agency_url, agency_timezone) FROM 'myFile.txt' CSV HEADER DELIMITER ','; 导出指定的行 https://stackoverflow.com/questions/12815496/export-specific-rows-from-a-postgresql-table-as-insert-sql-script ...

2026-03-20 · 22 min · 4503 words · -

SQLite

SQLite version: 3.44.0 SQLite 通过文件来保存数据库,一个文件就是一个数据库 commands # archlinux install sqlite sudo pacman -S sqlite # ubuntu sudo apt install sqlite3 # 打开一个已经存在的数据库 sqlite3 /var/lib/enx-api/enx.db # 启动 sqlite sqlite3 # 列出数据库文件和名字 .databases # query schema, 列出所有的表 .table # 查看表结构, 注意, 表名后面没有分号 .schema table0 # 创建数据库 sqlite3 /data/rssx/rssx.db # insert data insert into table_0 (name) values ('foo'); CREATE TABLE if not exists table_1 (name varchar(50) collate nocase PRIMARY KEY, create_time timestamp DEFAULT NULL); insert into table_1 (name) values ('foo'); insert into table_1 (name) values ('Foo'); -- Runtime error: UNIQUE constraint failed: table_1.name (19) # help .help # show tables .tables # insert # alter table, rename alter table feed rename to feeds; -- query that returns the size of a table in a SQLite database -- 空表的 size 是 4096 select sum("pgsize") from "dbstat" where name='table0'; -- drop table drop table table0; SQLite,是一种轻型的数据库,是遵守 ACID 的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它, 它占用资源非常地低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持 Windows/Linux/Unix 等等主流的操作系统, 同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起 MySQL、PostgreSQL 这两款开源世界著名的数据库管理系统来讲, 它的处理速度比他们都快。SQLite 第一个Alpha 版本诞生于2000年5月。 至今已经有12个年头,SQLite 也迎来了一个版本 SQLite 3 已经发布。 ...

2026-01-05 · 4 min · 669 words · -

kafka basic, command

kafka basic, command kafka_2.13-3.4.0.tgz scala 版本 2.13 kafka 版本 3.4.0 TLS kafka todo commands # list topic bin/kafka-topics.sh --list --bootstrap-server 127.0.0.1:9092 # create topic bin/kafka-topics.sh --create --partitions 1 --replication-factor 1 --topic topic_0 --bootstrap-server 127.0.0.1:9092 # consumer bin/kafka-console-consumer.sh --topic topic_0 --bootstrap-server 127.0.0.1:9092 # producer bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic topic_0 # list group name bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --list # 查看 consumer group offset bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --describe --group group0 # tls ./kafka-topics.sh --list --bootstrap-server 127.0.0.1:9093 --command-config /tmp/kafka.conf content of kafka.conf ...

2025-11-19 · 10 min · 1993 words · -

redis pipeline

“redis pipeline” why pipeline ? Redis 客户端与 server 的请求/响应模型 前面的文章 Redis 底层协议RESP详解 ,介绍到 redis 客户端与 redis-server 交互通信,采用的 TCP 请求/响应模型; 我们通过 Redis 客户端执行命令,如set key value,客户端遵循RESP协议,将命令的协议串发送给redis-server执行,redis-server执行完成后再同步返回结果。 手写Redis客户端-实现自己的Jedis 对这一过程进行了重点分析,并遵循RESP实现了自己简易版的Redis客户端。 Redis客户端与server通信,使用的是客户端-服务器 (CS) 模式;每次交互,都是完整的请求/响应模式。 这意味着通常情况下一个请求会遵循以下步骤: 客户端连接服务端,基于特定的端口,发送一个命令,并监听Socket返回,通常是以阻塞模式,等待服务端响应。 服务端处理命令,并将结果返回给客户端。 很显然,我们使用jedis或lettuce执行Redis命令,每次都是建立socket连接,并等待返回。 每个命令底层建立TCP连接的时间是省不掉的,即使我们都是在内网使用Redis,内网快但请求/响应的往返时间是不会减少的。 当需要对一组kv进行批量操作时,这组命令的耗时=sum(N*(建立连接时间+发送命令、返回结果的往返时间RTT)),随批量操作的key越多,时间累加呈线性增长。 顺理成章的,就出现了像数据库连接池等池化思想的衍生,redis连接也进行“池化”,如JedisPool。 JedisPool就足够了? 池化connection后,每次执行命令都从池子里“借”,用完之后再将connection“还”到池子。只是节省了创建TCP连接的时间; 当需要对一组kv进行批量操作时,JedisPool池子里的connection连接、极端情况都被用完了,怎么办? ——需要等待JedisPool池里有可复用的connection才能继续执行; redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool … Caused by: java.util.NoSuchElementException: Timeout waiting for idle object at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449) 如果在指定的等待时间内没有等到idle空闲连接,就报异常了。 尽管使用了池化、将connection进行复用,但不可避免的带来其他问题: https://jjlu521016.github.io/2018/12/09/JedisPool常见问题.html 除了池化的connection会被瞬间用完,Redis官网还给出了另外一个性能损耗的原因: It’s not just a matter of RTT https://redis.io/topics/pipelining 虽然池化的connection,节省了建立连接的时间,但多条命令(发送命令到sever、server返回结果)分别执行多次socket网络IO,涉及到read()和write() syscall系统调用,这意味着从用户态到内核态。上下文切换是巨大的速度损失。 ...

2021-07-24 · 1 min · 184 words · -

redis basic

redis basic commands redis-cli -h 127.0.0.1 -p 6379 # -a 使用认证密码登录 redis-cli -h 127.0.0.1 -p 6379 -a password0 # -n 指定 db redis-cli -h 127.0.0.1 -p 6379 -a password0 -n 10 # OBJECT ENCODING 命令可以查看一个数据库键的值对象的编码 OBJECT ENCODING key0 # 分析 redis key 大小 debug object key0 # Value at:0x7f6bffc22a00 refcount:1 encoding:raw serializedlength:7164 lru:12841785 lru_seconds_idle:95 # 查看各个库的 key 数量 info keyspace # 不进入交互模式, 直接执行命令 redis-cli -h 127.0.0.1 -p 6379 hget key0 field0 延迟时间 redis-cli --latency -h 192.168.50.100 -p 6379 sort https://segmentfault.com/a/1190000002806846 ...

2021-05-07 · 5 min · 1057 words · -

kafka 分区数

kafka 分区数 Kafka的分区数是不是越多越好? 分区多的优点 kafka使用分区将topic的消息打散到多个分区分布保存在不同的broker上,实现了producer和consumer消息处理的高吞吐量。Kafka的producer和consumer都可以多线程地并行操作,而每个线程处理的是一个分区的数据。因此分区实际上是调优Kafka并行度的最小单元。对于producer而言,它实际上是用多个线程并发地向不同分区所在的broker发起Socket连接同时给这些分区发送消息;而consumer,同一个消费组内的所有consumer线程都被指定topic的某一个分区进行消费。 所以说,如果一个topic分区越多,理论上整个集群所能达到的吞吐量就越大。 分区不是越多越好 分区是否越多越好呢?显然也不是,因为每个分区都有自己的开销: 一、客户端/服务器端需要使用的内存就越多 Kafka0.8.2之后,在客户端producer有个参数 batch.size,默认是16KB。它会为每个分区缓存消息,一旦满了就打包将消息批量发出。看上去这是个能够提升性能的设计。不过很显然,因为这个参数是分区级别的,如果分区数越多,这部分缓存所需的内存占用也会更多。假设你有10000个分区,按照默认设置,这部分缓存需要占用约157MB的内存。而consumer端呢?我们抛开获取数据所需的内存不说,只说线程的开销。如果还是假设有10000个分区,同时consumer线程数要匹配分区数(大部分情况下是最佳的消费吞吐量配置)的话,那么在consumer client就要创建10000个线程,也需要创建大约10000个Socket去获取分区数据。这里面的线程切换的开销本身已经不容小觑了。 服务器端的开销也不小,如果阅读Kafka源码的话可以发现,服务器端的很多组件都在内存中维护了分区级别的缓存,比如controller,FetcherManager等,因此分区数越多,这种缓存的成本就越大。 二、文件句柄的开销 每个分区在底层文件系统都有属于自己的一个目录。该目录下通常会有两个文件: base_offset.log和base_offset.index。Kafak的controller和ReplicaManager会为每个broker都保存这两个文件句柄(file handler)。很明显,如果分区数越多,所需要保持打开状态的文件句柄数也就越多,最终可能会突破你的ulimit -n的限制。 三、降低高可用性 Kafka通过副本(replica)机制来保证高可用。具体做法就是为每个分区保存若干个副本(replica_factor指定副本数)。每个副本保存在不同的broker上。期中的一个副本充当leader 副本,负责处理producer和consumer请求。其他副本充当follower角色,由Kafka controller负责保证与leader的同步。如果leader所在的broker挂掉了,contorller会检测到然后在zookeeper的帮助下重选出新的leader——这中间会有短暂的不可用时间窗口,虽然大部分情况下可能只是几毫秒级别。但如果你有10000个分区,10个broker,也就是说平均每个broker上有1000个分区。此时这个broker挂掉了,那么zookeeper和controller需要立即对这1000个分区进行leader选举。比起很少的分区leader选举而言,这必然要花更长的时间,并且通常不是线性累加的。如果这个broker还同时是controller情况就更糟了。 如何确定分区数量呢? 可以遵循一定的步骤来尝试确定分区数: 创建一个只有1个分区的topic,然后测试这个topic的producer吞吐量和consumer吞吐量。假设它们的值分别是Tp和Tc,单位可以是MB/s。然后假设总的目标吞吐量是Tt,那么分区数 = Tt / max(Tp, Tc) 说明: Tp表示producer的吞吐量。测试producer通常是很容易的,因为它的逻辑非常简单,就是直接发送消息到Kafka就好了。Tc表示consumer的吞吐量。测试Tc通常与应用的关系更大, 因为Tc的值取决于你拿到消息之后执行什么操作,因此Tc的测试通常也要麻烦一些。 ———————————————— 版权声明: 本文为CSDN博主「AlferWei」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接: https://blog.csdn.net/OiteBody/article/details/80595971

2019-11-27 · 1 min · 42 words · -

堆组织表、索引组织表、索引聚簇表

堆组织表、索引组织表、索引聚簇表 版权声明: 本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 https://blog.csdn.net/pianzif/article/details/32106971 堆组织表就不说了,其索引中记录了记录所在位置的rowid,查找的时候先找索引,然后再根据索引rowid找到块中的行数据 索引组织表,其行数据以索引形式存放,因此找到索引,就等于找到了行数据。 堆组织表的数据是散放的,索引和表的数据是分离的 索引组织表的索引和数据是在一起的 堆组织表的存储速度因为不用考虑排序, 所以存储速度会比较快. 但是要查找符合某个条件的记录, 就必须得读取全部的记录以便筛选. 而这个时候为了加快查询速度, 索引就出现了, 索引是针对少量特定字段的值拿出来进行排序存储, 并记录在表中的位置, 而因为索引是有序的, 所以就会很容易通过索引查询到具体的记录位置, 然后再根据记录位置直接从表中读取该记录. 同时因为索引的字段较少, 所以索引通常会比其基表小得多. 从上面通过索引访问表记录的方式可以看出, 当要访问的数据量较大时, 通过每一条记录的位置去访问原始记录, 每一条符合条件的记录都需要经过索引访问后再访问基表这样一个复杂的过程, 这会花费很多时间, 同样, 如果不经过索引而直接查询表, 也可能因为表字段太多, 记录较大的情况下把全部的数据读取进来, 这也会花费很多时间. 那怎么办呢? 这个时候就会想到, 如果表中数据本身就是有序的, 这样查询表的时候就可以快速的找到符合条件的记录位置, 而很容易判断符合条件记录的位置, 这样只需要读取一小部分数据出来就可以了, 不需要全表记录都读取出来进行判断. 索引表就这样产生了.当然索引表中插入,更新资料的时候可能会因为需要排序而将数据重组, 这时候数据插入或更新速度会比堆组织表慢一些. 如果堆组织表上有索引, 那么对堆组织表的插入也会因为要修改索引而变慢 我们可以看到堆组织表+索引的方式 与 索引表 都能够实现数据的快速查找, 那为什么不全部采用索引表呢, 这样不是很简单吗? 我能想到的是前者我们可以针对不同的查找条件建立多个索引, 而后者却不行, 后者只能对某一组查询条件有效 堆组织表 (heap organized table) Oracle中有很多类型的表,像堆组织表、索引组织表、索引聚簇表等等。首先,我将从最基本、最常用的堆组织表 (heap organized table) 介绍。 通常我们默认建的表就是堆组织表。语法 (详细语法请参见Oracle官方文档) 如下: Create table test( ...

2019-10-29 · 9 min · 1767 words · -

数据库事务, 锁

数据库事务, 锁 数据库锁 因为数据库要解决并发控制问题。在同一时刻,可能会有多个客户端对同一张表进行操作,比如有的在读取该行数据,其他的尝试去删除它。为了保证数据的一致性,数据库就要对这种并发操作进行控制,因此就有了锁的概念。 锁的分类 从对数据库操作的类型分 读锁(共享锁):针对同一块数据,多个读操作可以同时进行而不会互相影响。由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写。 写锁(排它锁):当当前写操作没有完成之前,它会阻断其他写锁和读锁。由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁。 从锁定的数据范围分 表锁:锁定某个表。 行锁 :锁定某行。 为了尽可能 提高数据库的并发度,每次锁定的数据范围越小越好。理论上每次只锁定当前操作的数据的方案会得到最大的并发度,但是管理锁是很耗费资源的事情。因此数据库系统需要在高并发响应和系统性能两方面进行平衡,这样就产生了“锁粒度”的概念。 锁粒度 表锁:管理锁的开销最小,同时允许的并发量也最小的锁机制。MyIsam存储引擎使用的锁机制。当要写入数据时,把整个表都锁上,此时其他读、写动作一律等待。在MySql中,除了MyIsam存储引擎使用这种锁策略外,MySql本身也使用表锁来执行某些特定动作,比如alter table. 行锁:可以支持最大并发的锁策略。InnoDB和Falcon两张存储引擎都采用这种策略。 MySql是一种开放的架构,你可以实现自己的存储引擎,并实现自己的锁粒度策略,不像Oracle,你没有机会改变锁策略,Oracle采用的是行锁。从大到小,mysql服务器仅支持表级锁,行锁需要存储引擎完成。粒度越精细,并发性越好。即行锁的并发性最好,但需要存储引擎的支持。 数据库事务有不同的隔离级别,不同的隔离级别对锁的使用是不同的,锁的应用最终导致不同事务的隔离级别。 事务和锁机制是什么关系? 开启事务就自动加锁了吗? 1、事务与锁是不同的。事务具有ACID(原子性、一致性、隔离性和持久性),锁是用于解决隔离性的一种机制。 2、事务的隔离级别通过锁的机制来实现。另外锁有不同的粒度,同时事务也是有不同的隔离级别的。 3、开启事务就自动加锁。 ql规范定义的事务的隔离级别: 1.READ UNCOMMITTED(读取未提交内容) 所有事务可以看到未提交事务的执行结果,本隔离级别很少用到实际应用中,读取未提交的数据,又称为“脏读”。 2.READ COMMITTED(读取提交内容) 大多数数据库的默认隔离级别是此级别,但不是MySQL默认的。一个事务在开始的时候只能看见已提交事务所做的改变。一个事务从开始到提交前所做的任何改变都是不可见的,除非提交。这种隔离级别也称为不可重复读。 3.REPEATABLE READ(可重复读) 此隔离级别是为了解决不可重复读隔离级别导致的问题即一个事务多个实例并发读取数据时会看到不同的结果。可重复读描述的是一个事务在处理数据时,多次查询此数据得到的结果是一样的。MySQL的InnoDB存储引擎通过多版本并发控制(Multi_Version Concurrency Control, MVCC)机制来解决该问题。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时, 另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。(幻读描述的是MVCC不能阻止插入新的数据,导致多次查询时数据记录不一致。) 4.SERIALIZABLE(可串行化) 可串行化是最高的隔离级别,它通过强制事务排序,使之不可重读,解决了幻读的问题。此隔离级别会在每个读的数据行上加共享锁,使用这种隔离级别会产生大量的超时现象,一般实际开发中不会用到。该类型在A客户端操作test.test1表时会锁定该数据,如果B客户端想要操作test.test1就需要等待A客户端释放。 这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如: 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。 mysql加锁机制: 根据类型可分为共享锁(SHARED LOCK)和排他锁(EXCLUSIVE LOCK)或者叫读锁(READ LOCK)和写锁(WRITE LOCK)。 根据粒度划分又分表锁和行锁。表锁由数据库服务器实现,行锁由存储引擎实现。 mysql提供了3种事务型存储引擎,InnDB、NDB Cluster和Falcon。 一个事务执行的任何过程中都可以获得锁,但是只有事务提交或回滚的时候才释放这些锁。这些都是隐式锁定,也可以显式锁定,InnoDB支持显式锁定,例如: SELECT …. LOCK IN SHARE MODE (加共享锁) SELECT …..FOR UPDATE(加排他锁) ...

2019-09-09 · 1 min · 102 words · -

redis stream

redis stream stream是一个看起来比pubsub可靠多的消息队列。pubsub不靠谱? 很不靠谱,网络一断或buffer一大就会主动清理数据。stream的设计参考了kafka的消费组模型,redis作者antirez也专门写了篇短文描述了这个过程。 说起新鲜的redis streams,其实Antirez在几年前开了一个新项目叫做disque, 也是用来做消息队列的,奈何没怎么有人关注。我作为antirez的粉丝,肯定是用过了,还tmd改过disque python的库。现在redis5的stream里有一些disque的影子。 更多streams的信息 https://redis.io/topics/streams-intro Redis5.0最近被作者突然放出来了,增加了很多新的特色功能。而Redis5.0最大的新特性就是多出了一个数据结构Stream,它是一个新的强大的支持多播的可持久化的消息队列,作者坦言Redis Stream狠狠地借鉴了Kafka的设计。 Redis Stream 有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的ID和对应的内容。消息是持久化的,Redis重启后,内容还在。 每个Stream都有唯一的名称,它就是Redis的key,在我们首次使用xadd指令追加消息时自动创建。 每个Stream都可以挂多个消费组,每个消费组会有个游标 last_delivered_id 在 Stream 数组之上往前移动,表示当前消费组已经消费到哪条消息了。每个消费组都有一个Stream内唯一的名称,消费组不会自动创建,它需要单独的指令 xgroup create进行创建,需要指定从Stream的某个消息ID开始消费,这个ID用来初始化last_delivered_id变量。 每个消费组(Consumer Group)的状态都是独立的,相互不受影响。也就是说同一份Stream内部的消息会被每个消费组都消费到。 同一个消费组(Consumer Group)可以挂接多个消费者(Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。每个消费者者有一个组内唯一名称。 消费者(Consumer)内部会有个状态变量pending_ids,它记录了当前已经被客户端读取的消息,但是还没有ack。如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack,它就开始减少。这个pending_ids变量在Redis官方被称之为PEL,也就是Pending Entries List,这是一个很核心的数据结构,它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理。 http://xiaorui.cc/2018/06/07/%E6%B5%85%E5%85%A5%E6%B5%85%E5%87%BAredis5-0%E7%9A%84streams%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ https://toutiao.io/posts/2agvp3/preview

2019-08-06 · 1 min · 32 words · -

MySQL int 长度

MySQL int 长度 “浮点型"的长度是用来限制数字存储范围的. 比如 float(3,2) 只能够写入 0.00~999.99. “整型"的长度并不会限制存储的数字范围. 比如, int 和 int(3) 的存储范围都是 -2147483648 ~ 2147483647, int unsigned 和 int(3) unsigned 的存储范围都是0 ~ 4294967295. “整型"的长度实际上可以理解为"显示长度”, 如果该字段开启 “Zerofill/补零"就能很明显地知道它的作用. 参考 “高性能MySQL” 的说明 “高性能MySQL” 书中在"4.1 选择优化的数据类型"中提到: MySQL 可以为整数类型指定宽度, 例如 INT(11), 对大多数应用这是没有意义的: 它不会限制值的合法范围, 只是规定了 MySQL 的一些交互工具(例如 MySQL 命令行客户端)用来显示字符的个数. 对于存储和计算来说, INT(1) 和 INT(20) 是相同的 “MySQL 手册"的说明 MySQL 5.7 手册 “12.2.5 Numeric Type Attributes”: MySQL supports an extension for optionally specifying the display width of integer data types in parentheses following the base keyword for the type. For example, INT(4) specifies an INT with a display width of four digits. This optional display width may be used by applications to display integer values having a width less than the width specified for the column by left-padding them with spaces. (That is, this width is present in the metadata returned with result sets. Whether it is used or not is up to the application.) ...

2019-08-06 · 2 min · 295 words · -

kafka consumer

kafka consumer 按照 Kafka 默认的消费逻辑设定,一个分区只能被同一个消费组(ConsumerGroup)内的一个消费者消费。 即同一个partition内的消息只能被同一个组中的一个consumer消费。当消费者数量多于partition的数量时,多余的消费者空闲 assignment, 分配策略 Kafka提供了消费者客户端参数partition.assignment.strategy用来设置消费者与订阅主题之间的分区分配策略。 默认情况下,此参数的值为:org.apache.kafka.clients.consumer.RangeAssignor,即采用RangeAssignor分配策略。除此之外,Kafka中还提供了另外两种分配策略: RoundRobinAssignor和StickyAssignor。消费者客户端参数partition.asssignment.strategy可以配置多个分配策略,彼此之间以逗号分隔。 RangeAssignor RangeAssignor 策略的原理是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个topic,RangeAssignor策略会将消费组内所有订阅这个topic的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。 range assignor 在某些情况下会分配不均匀, 有可能会出现部分消费者过载的情况. RoundRobinAssignor 把 topic 和 consumer 排序, 依次给 topic 分配 consumer, 同一个 topic 中的不同 partition 分被均匀分配给不同的 consumer. RoundRobinAssignor 策略的原理是将消费组内所有消费者以及消费者所订阅的所有topic的partition按照字典序排序,然后通过轮询消费者方式逐个将分区分配给每个消费者。RoundRobinAssignor策略对应的partition.assignment.strategy参数值为:org.apache.kafka.clients.consumer.RoundRobinAssignor。 如果同一个消费组内所有的消费者的订阅信息都是相同的,那么RoundRobinAssignor策略的分区分配会是均匀的。 如果同一个消费组内的消费者所订阅的Topic 是不相同的,那么在执行分区分配的时候就不是完全的轮询分配,有可能会导致分区分配的不均匀。如果某个消费者没有订阅消费组内的某个topic,那么在分配分区的时候此消费者将分配不到这个topic的任何分区。 StickyAssignor “sticky”这个单词可以翻译为“粘性的”,Kafka从0.11.x版本开始引入这种分配策略,它主要有两个目的: ① 分区的分配要尽可能的均匀; ② 分区的分配尽可能的与上次分配的保持相同。 当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor策略的具体实现要比RangeAssignor和RoundRobinAssignor这两种分配策略要复杂很多。 从结果上看StickyAssignor策略比另外两者分配策略而言显得更加的优异,这个策略的代码实现也是异常复杂,如果大家在一个 group 里面,不同的 Consumer 订阅不同的 topic, 那么设置Sticky 分配策略还是很有必要的。 properties.put("enable.auto.commit", "true"); properties.put("auto.commit.interval.ms", "1000"); properties.put("auto.offset.reset", "latest"); properties.put("session.timeout.ms", "30000"); properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); properties.put("value.deserializer", "org.apache.kafka.common.serialization.ByteArrayDeserializer"); Consumer Group 主要用于实现高伸缩性,高容错性的 Consumer 机制。因此,消息的接收是基于 Consumer Group 的。组内多个 Consumer 实例可以同时读取 Kafka 消息,同一时刻一条消息只能被一个消费者消费,而且一旦某一个 consumer “挂了”, Consumer Group 会立即将已经崩溃的 Consumer 负责的分区转交给其他 Consumer 来负责。从而保证 Consumer Group 能够正常工作。 ...

2019-05-21 · 3 min · 557 words · -

Kafka, offset

Kafka, offset offset的保存 一个消费组消费partition,需要保存offset记录消费到哪,以前保存在zk中,由于zk的写性能不好,以前的解决方法都是consumer每隔一分钟上报一次。这里zk的性能严重影响了消费的速度,而且很容易出现重复消费。 在0.10版本后,kafka把这个offset的保存,从zk总剥离,保存在一个名叫__consumeroffsets topic的topic中。写进消息的key由groupid、topic、partition组成,value是偏移量offset。topic配置的清理策略是compact。总是保留最新的key,其余删掉。一般情况下,每个key的offset都是缓存在内存中,查询的时候不用遍历partition,如果没有缓存,第一次就会遍历partition建立缓存,然后查询返回。 作者: 123archu 链接: https://www.jianshu.com/p/d3e963ff8b70 来源: 简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。 https://blog.csdn.net/u012129558/article/details/80075270 对Kafka offset的管理,一直没有进行系统的总结,这篇文章对它进行分析。 什么是offset offset是consumer position,Topic的每个Partition都有各自的offset. Keeping track of what has been consumed, is, surprisingly, one of the key performance points of a messaging system. Most messaging systems keep metadata about what messages have been consumed on the broker. That is, as a message is handed out to a consumer, the broker either records that fact locally immediately or it may wait for acknowledgement from the consumer. This is a fairly intuitive choice, and indeed for a single machine server it is not clear where else this state could go. Since the data structure used for storage in many messaging systems scale poorly, this is also a pragmatic choice-since the broker knows what is consumed it can immediately delete it, keeping the data size small. ...

2019-05-13 · 4 min · 713 words · -

golang kafka

golang kafka https://github.com/Shopify/sarama https://github.com/bsm/sarama-cluster

2019-05-10 · 1 min · 4 words · -

Kafka 文件存储机制

Kafka 文件存储机制 Kafka 是什么 Kafka 是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx日志、访问日志,消息服务等等,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。 1.前言 一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一。 下面将从Kafka文件存储机制和物理结构角度,分析Kafka是如何实现高效文件存储,及实际应用效果。 2.Kafka文件存储机制 Kafka部分名词解释如下: Broker: 消息中间件处理结点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群。 Topic: 一类消息,例如page view日志、click日志等都可以以topic的形式存在,Kafka集群能够同时负责多个topic的分发。 Partition: topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列。 Segment: partition物理上由多个segment组成,下面2.2和2.3有详细说明。 offset: 每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。partition中的每个消息都有一个连续的序列号叫做offset,用于partition唯一标识一条消息. 分析过程分为以下4个步骤: topic中partition存储分布 partiton中文件存储方式 partiton中segment文件存储结构 在partition中如何通过offset查找message 通过上述4过程详细分析,我们就可以清楚认识到kafka文件存储机制的奥秘。 2.1 topic中partition存储分布 假设实验环境中Kafka集群只有一个broker,xxx/message-folder为数据文件存储根目录,在Kafka broker中server.properties文件配置(参数log.dirs=xxx/message-folder),例如创建2个topic名称分别为report_push、launch_info, partitions数量都为partitions=4 存储路径和目录规则为: 复制代码 xxx/message-folder |--report_push-0 |--report_push-1 |--report_push-2 |--report_push-3 |--launch_info-0 |--launch_info-1 |--launch_info-2 |--launch_info-3 复制代码 在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。 如果是多broker分布情况,请参考kafka集群partition分布原理分析 2.2 partiton中文件存储方式 下面示意图形象说明了partition中文件存储方式: image 图1 每个partion(目录)相当于一个巨型文件被平均分配到多个大小相等segment(段)数据文件中。但每个段segment file消息数量不一定相等,这种特性方便old segment file快速被删除。 每个partiton只需要支持顺序读写就行了,segment文件生命周期由服务端配置参数决定。 这样做的好处就是能快速删除无用文件,有效提高磁盘利用率。 2.3 partiton中segment文件存储结构 读者从2.2节了解到Kafka文件系统partition存储方式,本节深入分析partion中segment file组成和物理结构。 segment file组成: 由2大部分组成,分别为index file和data file,此2个文件一一对应,成对出现,后缀".index"和".log"分别表示为segment索引文件、数据文件. ...

2019-05-10 · 5 min · 878 words · -

redis config redis 配置

redis config redis 配置 sample, 单机 redis server 配置 bind 0.0.0.0 protected-mode no port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no pidfile /var/run/redis_6379.pid loglevel notice logfile "" databases 16 always-show-logo no set-proc-title yes proc-title-template "{title} {listen-addr} {server-mode}" stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb rdb-del-sync-files no dir /var/lib/redis replica-serve-stale-data yes replica-read-only yes repl-diskless-sync yes repl-diskless-sync-delay 5 repl-diskless-sync-max-replicas 0 repl-diskless-load disabled repl-disable-tcp-nodelay no replica-priority 100 acllog-max-len 128 lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no replica-lazy-flush no lazyfree-lazy-user-del no lazyfree-lazy-user-flush no oom-score-adj no oom-score-adj-values 0 200 800 disable-thp yes appendonly no appendfilename "appendonly.aof" appenddirname "appendonlydir" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble yes aof-timestamp-enabled no slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-listpack-entries 512 hash-max-listpack-value 64 list-max-listpack-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-listpack-entries 128 zset-max-listpack-value 64 hll-sparse-max-bytes 3000 stream-node-max-bytes 4096 stream-node-max-entries 100 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 dynamic-hz yes aof-rewrite-incremental-fsync yes rdb-save-incremental-fsync yes jemalloc-bg-thread yes https://raw.githubusercontent.com/redis/redis/6.0/redis.conf ...

2019-02-22 · 7 min · 1353 words · -

聚合函数 aggregation function, UNION, UNION ALL

聚合函数 aggregation function, UNION, UNION ALL 聚合函数 (aggregation function) -也就是组函数 在一个行的集合 (一组行) 上进行操作,对每个组给一个结果。 集合查询操作 union 去重 union用于把两个或者多个select查询的结果集合并成一个 默认情况下,UNION = UNION DISTINCT 进行合并的两个查询,其SELECT列表必须在数量和对应列的数据类型上保持一致; 默认会去掉两个查询结果集中的重复行;默认结果集不排序; 最终结果集的列名来自于第一个查询的SELECT列表 union all 不去重 UNION ALL 不去掉结果集中重复的行 SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...] 常用的组函数: AVG([distinct] expr) 求平均值 COUNT({*|[distinct] } expr) 统计行的数量 MAX([distinct] expr) 求最大值 MIN([distinct] expr) 求最小值 SUM([distinct] expr) 求累加和 ①每个组函数接收一个参数 ②默认情况下,组函数忽略列值为null的行,不参与计算 ③有时,会使用关键字distinct剔除字段值重复的条数 注意: 当使用组函数的select语句中没有group by子句时,中间结果集中的所有行自动形成一组,然后计算组函数; 组函数不允许嵌套,例如: count(max(…)); 组函数的参数可以是列或是函数表达式; ...

2018-08-14 · 6 min · 1161 words · -

kafka, rabbitmq

kafka, rabbitmq http://www.infoq.com/cn/articles/kafka-vs-rabbitmq?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global

2018-05-14 · 1 min · 3 words · -

kafka cluster

kafka cluster version: 3.0.0 # net podman run \ --name zookeeper \ -p 2181:2181 \ -v /etc/localtime:/etc/localtime:ro \ -v zookeeper-conf:/conf \ -v zookeeper-data:/data \ -v zookeeper-datalog:/datalog \ -e ZOO_4LW_COMMANDS_WHITELIST=* \ -d \ zookeeper:3.7.0 podman run -d --name kafka1 \ -e ALLOW_PLAINTEXT_LISTENER=yes \ -e KAFKA_CFG_ZOOKEEPER_CONNECT=192.168.50.169:2181 \ -e KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.50.169:9092 \ -p 9092:9092 \ bitnami/kafka:3.2.0 podman run -d --name kafka2 \ -e ALLOW_PLAINTEXT_LISTENER=yes \ -e KAFKA_CFG_ZOOKEEPER_CONNECT=192.168.50.169:2181 \ -e KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.50.169:9093 \ -p 9093:9092 \ bitnami/kafka:3.2.0 podman run -d --name kafka3 \ -e ALLOW_PLAINTEXT_LISTENER=yes \ -e KAFKA_CFG_ZOOKEEPER_CONNECT=192.168.50.169:2181 \ -e KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.50.169:9094 \ -p 9094:9092 \ bitnami/kafka:3.2.0 https://github.com/bitnami/bitnami-docker-kafka/blob/master/README.md ...

2018-05-07 · 1 min · 95 words · -

MySQL using having

MySQL using having http://wuzhangshu927.blog.163.com/blog/static/1142246872010113093426574/ USING() using 可用在 join 语句相同字段连接, 起到和 ON 相同作用, inner join 和 left join 中都可以使用 LEFT JOIN 正常写法: SELECT t1.id,t2.name FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE .... 其实也可以这么写: SELECT t1.id,t2.name FROM t1 LEFT JOIN t2 USING(id) WHERE .... HAVING MySQL 中的 where 和 having 子句都可以实现筛选记录的功能, having 可以认为是对 where 的补充, 因为它可以对分组数据进行再次判断, 一般跟在 group by 后面, 并可以使用聚集函数 (sum, min, max, avg, count) SELECT `uid`, SUM(`points`) num FROM table GROUP BY `uid` HAVING num > 1000

2017-11-22 · 1 min · 78 words · -

grpc

python grpc grpcio==1.48.2 grpc 会忽略 linux 环境变量 里配置的 no_proxy, 导致请求失败, 在启动客户端之前 临时删除环境变量 unset HTTP_PROXY golang grpc gRPC 通过 HTTP2 协议传输 定义协议 protobuf syntax = "proto3"; message SearchRequest { string query = 1; int32 page_number = 2; int32 results_per_page = 3; } 生成 python 文件 python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. logServer.proto python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. .\tests\remote\grpc_wrapper\service.proto golang grpc install protocol compiler plugins 在 https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go 可以看到最新的版本号 go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.27.1 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0 # 安装后查看 版本 ./protoc-gen-go --version ./protoc-gen-go-grpc --version protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ helloworld/helloworld.proto protoc -I proto/ proto/helloworld.proto -go_out=plugins=grpc:proto grpc-dump go install github.com/bradleyjkemp/grpc-tools/grpc-dump@latest grpc-dump --port=12345 http_proxy=http://localhost:12345 my-app wireshark grpc https://mp.weixin.qq.com/s/BdcFRO58ytrtcpYZVT1ymQ ...

2017-09-07 · 1 min · 133 words · -