首先明确说明Kafka不是数据库,它没有schema,也没有表,更没有索引。
1.它仅仅是生产消息流、消费消息流而已。从这个角度来说Kafka的确不像数据库,至少不像我们熟知的关系型数据库。
那么到底什么是数据库呢?或者说什么特性使得一个系统可以被称为数据库?经典的教科书是这么说的:数据库是提供 ACID 特性的,我们依次讨论下ACID。
1、持久性(durability)
我们先从最容易的持久性开始说起,因为持久性最容易理解。在80年代持久性指的是把数据写入到磁带中,这是一种很古老的存储设备,现在应该已经绝迹了。目前实现持久性更常见的做法是将数据写入到物理磁盘上,而这也只能实现单机的持久性。当演进到分布式系统时代后,持久性指的是将数据通过备份机制拷贝到多台机器的磁盘上。很多数据库厂商都有自己的分布式系统解决方案,如GreenPlum和Oracle RAC。它们都提供了这种多机备份的持久性。和它们类似,Apache Kafka天然也是支持这种持久性的,它提供的副本机制在实现原理上几乎和数据库厂商的方案是一样的。
2、原子性(atomicity)
数据库中的原子性和多线程领域内的原子性不是一回事。我们知道在Java中有AtomicInteger这样的类能够提供线程安全的整数 *** 作服务,这里的atomicity关心的是在多个线程并发的情况下如何保证正确性的问题。而在数据库领域,原子性关心的是如何应对错误或异常情况,特别是对于事务的处理。如果服务发生故障,之前提交的事务要保证已经持久化,而当前运行的事务要终止(abort),它执行的所有 *** 作都要回滚,最终的状态就好像该事务从未运行过那样。举个实际的例子,
第三个方法是采用基于日志结构的消息队列来实现,比如使用Kafka来做,如下图所示:
在这个架构中app仅仅是向Kafka写入消息,而下面的数据库、cache和index作为独立的consumer消费这个日志——Kafka分区的顺序性保证了app端更新 *** 作的顺序性。如果某个consumer消费速度慢于其他consumer也没关系,毕竟消息依然在Kafka中保存着。总而言之,有了Kafka所有的异质系统都能以相同的顺序应用app端的更新 *** 作,
3、隔离性(isolation)
在传统的关系型数据库中最强的隔离级别通常是指serializability,国内一般翻译成可串行化或串行化。表达的思想就是连接数据库的每个客户端在执行各自的事务时数据库会给它们一个假象:仿佛每个客户端的事务都顺序执行的,即执行完一个事务之后再开始执行下一个事务。其实数据库端同时会处理多个事务,但serializability保证了它们就像单独执行一样。举个例子,在一个论坛系统中,每个新用户都需要注册一个唯一的用户名。一个简单的app实现逻辑大概是这样的:
4、一致性(consistency)
最后说说一致性。按照Kelppmann大神的原话,这是一个很奇怪的属性:在所有ACID特性中,其他三项特性的确属于数据库层面需要实现或保证的,但只有一致性是由用户来保证的。严格来说,它不属于数据库的特性,而应该属于使用数据库的一种方式。坦率说第一次听到这句话时我本人还是有点震惊的,因为从没有往这个方面考虑过,但仔细想想还真是这么回事。比如刚才的注册用户名的例子中我们要求每个用户名是唯一的。这种一致性约束是由我们用户做出的,而不是数据库本身。数据库本身并不关心或并不知道用户名是否应该是唯一的。针对Kafka而言,这种一致性又意味着什么呢?Kelppmann没有具体展开,
希望能帮到你,谢谢!
以添加Socket数据库批量打印为例子来进行 *** 作;
根据标签纸实际尺寸设置纸张尺寸,然后点击上方工具栏中的数据库设置图标,在d出窗口中点击“添加”选择最下方的“Socket数据源”:
在d出窗口中填写各项Socket参数(地址、端口、编码等)。如果需用多字段,Socket返回字符串中请用分隔符拼接多字段内容,如:111111,222222,333333。数据源设置窗口中的“分隔符号”请选择对应分隔符,填写完毕后点击“添加-关闭”即可:
添加标签可变内容 此处添加对象,可以是文字、图片、条形码、二维码等,本文我们使用文字来演示添加方式。
点击左侧工具栏中的“A”,在画布上绘制普通文本并双击普通文本即可打开其“图形属性”窗口,然后点击“数据源”,可在此窗口中添加内容:
添加内容时,点击“数据源”窗口左侧“修改”按钮,将添加方式修改为“数据库导入”并选择所连接的Socket数据库及对应字段,点击编辑即可看到数据源中的内容,然后再点击“确定”即可将Socket数据库中的内容添加到画布上。
预览及打印 可变数据添加完毕预览的时候可以翻页查看并核对一下数据,确认无误后就可以点击打印机图标连接打印机打印了。
在连接Socket数据库时还需注意以下几个方面:
1、该服务器上提前应运行对应的Socket通讯响应的服务程序;
2、当打印软件提交数据获取指令(get01)时,该服务程序应及时返回一条打印数据;
3、当打印软件提交的指令有“##”前缀时,则为预览数据请求,服务程序视情况进行响应。
可以连接到一个网络服务器并且能够从这个服务器下载指定的URL,程序中直接使用HTTP协议。程序将定义一个输出流,下载的URL的内容将来被写入这个流,通过socket来获得输入和输出流:view sourceprint?
01import java.io.*
02import java.net.*
03public class HttpClient {
04public static void main(String[] args) {
05try {
06// Demo参数:
07if ((args.length != 1) &&(args.length != 2))
08throw new IllegalArgumentException("Wrong number of args")
09//定义输出流,下载的URL内容被写入这个流
10OutputStream to_file
11if (args.length == 2) to_file = new FileOutputStream(args[1])
12else to_file = System.out
13//使用URL类来把用户指定的URL解析成几个部分
14URL url = new URL(args[0])
15String protocol = url.getProtocol()
16if (!protocol.equals("http")) // 检验是否满足支持的协议
17throw new IllegalArgumentException("Must use 'http:' protocol")
18String host = url.getHost()
19int port = url.getPort()
20if (port == -1) port = 80//如果没有指定端口,用默认端口
21String filename = url.getFile()
22// 打开一个连接到指定主机和端口的网络socket连接
23Socket socket = new Socket(host, port)
24// 通过socket来获得输入和输出流
25InputStream from_server = socket.getInputStream()
26PrintWriter to_server = new PrintWriter(socket.getOutputStream())
27
28// 发送HTTP GET命令给网络服务器,指定要下载的文件
29// 使用了一个老版本非常简单的HTTP协议
30to_server.print("GET " + filename + "\n\n")
31to_server.flush()// 立即发送
32// 现在读取服务器的响应,把接收到的内容写入文件
33byte[] buffer = new byte[4096]
34int bytes_read
35while((bytes_read = from_server.read(buffer)) != -1)
36to_file.write(buffer, 0, bytes_read)
37// 当服务器关闭连接时,也关闭stuff
38socket.close()
39to_file.close()
40}
41catch (Exception e) { // 发布错误
42System.err.println(e)
43System.err.println("Usage: java HttpClient <URL>[<filename>]")
44}
45}
46}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)