1. 程式人生 > >快取一致性和跨伺服器查詢的資料異構解決方案canal

快取一致性和跨伺服器查詢的資料異構解決方案canal

當你的專案資料量上去了之後,通常會遇到兩種情況,第一種情況應是最大可能的使用cache來對抗上層的高併發,第二種情況同樣也是需要使用分庫

分表對抗上層的高併發。。。逼逼逼起來容易,做起來並不那麼樂觀,由此引入的問題,不見得你有好的解決方案,下面就具體分享下。

一:儘可能的使用Cache

       比如在我們的千人千面系統中,會針對商品,訂單等維度為某一個商家店鋪自動化建立大約400個數據模型,然後買家在淘寶下訂單之後,淘寶會將訂單推

送過來,訂單會在400個模型中兜一圈,從而推送更貼切符合該買家行為習慣的簡訊和郵件,這是一個真實的業務場景,為了應對高併發,這些模型自然都是緩

存在Cache中,模型都是從db中灌到redis的,那如果有新的模型進來了,我如何通知redis進行快取更新呢???通常的做法就是在新增模型的時候,順便更新

redis。。。對吧,如下圖:

說的簡單,web開發的程式設計師會說,麻蛋的,我管你什麼業務,更新你妹啊。。。我把自己的手頭程式碼寫好就可以了,我要高內聚,所以你必須碰一鼻子灰。

除了一鼻子灰之後,也許你還會遇到更新database成功,再更新redis的時候失敗,可人家不管,而且錯誤日誌還是別人的日誌系統裡面,所以你很難甚至

無法保證這個db和cache的快取一致性,那這個時候能不能換個思路,我直接寫個程式訂閱database的binlog,從binlog中分析出模型資料的CURD操作,根

據這些CURD的實際情況更新Redis的快取資料,第一個可以實現和web的解耦,第二個實現了高度的快取一致性,所以新的架構是這樣的。

上面這張圖,相信大家都能看得懂,重點就是這個處理binlog程式,從binlog中分析出CURD從而更新Redis,其實這個binlog程式就是本篇所說的canal。。。

一個偽裝成mysql的slave,不斷的通過dump命令從mysql中盜出binlog日誌,從而完美的實現了這個需求。

二:資料異構    

       本篇開頭也說到了,資料量大了之後,必然會存在分庫分表,甚至database都要分散到多臺伺服器上,現在的電商專案,都是業務趕著技術跑。。。

誰也不知道下一個業務會是一個怎樣的奇葩,所以必然會導致你要做一些跨伺服器join查詢,你以為自己很聰明,其實DBA早就把跨伺服器查詢的函式給你

關掉了,求爹爹拜奶奶都不會給你開的,除非你殺一個DBA祭天,不過如果你的業務真的很重要,可能DBA會給你做資料異構,所謂的資料異構,那就是

將需要join查詢的多表按照某一個維度又聚合在一個DB中。讓你去查詢。。。。。

那如果用canal來訂閱binlog,就可以改造成下面這種架構。

三:搭建一覽

     好了,canal的應用場景給大家也介紹到了,最主要是理解這種思想,人家搞不定的東西,你的價值就出來了。

1.  開啟mysql的binlog功能

        開啟binlog,並且將binlog的格式改為Row,這樣就可以獲取到CURD的二進位制內容,windows上的路徑為:C:\ProgramData\MySQL\MySQL Server 5.7\my.ini。

1 log-bin=mysql-bin #新增這一行就ok
2 binlog-format=ROW #選擇row模式
3 server_id=1 

 

2. 驗證binlog是否開啟

       使用命令驗證,並且開啟binlog的過期時間為30天,預設情況下binlog是不過期的,這就導致你的磁碟可能會爆滿,直到掛掉。

1 show variables like 'log_%';
2 
3 #設定binlog的過期時間為30天
4 show variables like '%expire_logs_days%';
5 set global expire_logs_days=30;

 3. 給canal伺服器分配一個mysql的賬號許可權,方便canal去偷binlog日誌。

CREATE USER canal IDENTIFIED BY 'canal';    
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';  
FLUSH PRIVILEGES;  

show grants for 'canal'  

4. 下載canal

 github的地址: https://github.com/alibaba/canal/releases

5. 然後就是各種tar解壓 canal.deployer-1.0.24.tar.gz  => canal

複製程式碼

[[email protected] myapp]# ls
apache-maven-3.5.0-bin.tar.gz                        dubbo-monitor-simple-2.5.4-SNAPSHOT.jar     nginx                tengine-2.2.0.tar.gz
canal                                                gearmand                                    nginx-1.13.4.tar.gz  tengine_st
canal.deployer-1.0.24.tar.gz                         gearmand-1.1.17                             nginx_st             tomcat
dubbo                                                gearmand-1.1.17.tar.gz                      redis                zookeeper
dubbo-monitor-simple-2.5.4-SNAPSHOT                  maven                                       redis-4.0.1.tar.gz   zookeeper-3.4.9.tar.gz
dubbo-monitor-simple-2.5.4-SNAPSHOT-assembly.tar.gz  mysql-5.7.19-linux-glibc2.12-x86_64.tar.gz  tengine
[[email protected] myapp]# cd canal
[[email protected] canal]# ls
bin  conf  lib  logs
[[email protected] canal]# cd conf
[[email protected] conf]# ls
canal.properties  example  logback.xml  spring
[[email protected] conf]# cd example
[[email protected] example]# ls
instance.properties  meta.dat
[[email protected] example]# 

複製程式碼

6. canal 和 instance 配置檔案

     canal的模式是這樣的,一個canal裡面可能會有多個instance,也就說一個instance可以監控一個mysql例項,多個instance也就可以對應多臺伺服器

的mysql例項。也就是一個canal就可以監控分庫分表下的多機器mysql。

《1》 canal.properties

      它是全域性性的canal伺服器配置,具體如下,這裡面的引數涉及到方方面面。

複製程式碼

#################################################
#########               common argument         ############# 
#################################################
canal.id= 1
canal.ip=
canal.port= 11111
canal.zkServers=
# flush data to zk
canal.zookeeper.flush.period = 1000
# flush meta cursor/parse position to file
canal.file.data.dir = ${canal.conf.dir}
canal.file.flush.period = 1000
## memory store RingBuffer size, should be Math.pow(2,n)
canal.instance.memory.buffer.size = 16384
## memory store RingBuffer used memory unit size , default 1kb
canal.instance.memory.buffer.memunit = 1024 
## meory store gets mode used MEMSIZE or ITEMSIZE
canal.instance.memory.batch.mode = MEMSIZE
    
## detecing config
canal.instance.detecting.enable = false
#canal.instance.detecting.sql = insert into retl.xdual values(1,now()) on duplicate key update x=now()
canal.instance.detecting.sql = select 1
canal.instance.detecting.interval.time = 3
canal.instance.detecting.retry.threshold = 3
canal.instance.detecting.heartbeatHaEnable = false

# support maximum transaction size, more than the size of the transaction will be cut into multiple transactions delivery
canal.instance.transaction.size =  1024
# mysql fallback connected to new master should fallback times
canal.instance.fallbackIntervalInSeconds = 60

# network config
canal.instance.network.receiveBufferSize = 16384
canal.instance.network.sendBufferSize = 16384
canal.instance.network.soTimeout = 30

# binlog filter config
canal.instance.filter.query.dcl = false
canal.instance.filter.query.dml = false
canal.instance.filter.query.ddl = false
canal.instance.filter.table.error = false
canal.instance.filter.rows = false

# binlog format/image check
canal.instance.binlog.format = ROW,STATEMENT,MIXED 
canal.instance.binlog.image = FULL,MINIMAL,NOBLOB

# binlog ddl isolation
canal.instance.get.ddl.isolation = false

#################################################
#########               destinations            ############# 
#################################################
canal.destinations= example
# conf root dir
canal.conf.dir = ../conf
# auto scan instance dir add/remove and start/stop instance
canal.auto.scan = true
canal.auto.scan.interval = 5

canal.instance.global.mode = spring 
canal.instance.global.lazy = false
#canal.instance.global.manager.address = 127.0.0.1:1099
#canal.instance.global.spring.xml = classpath:spring/memory-instance.xml
canal.instance.global.spring.xml = classpath:spring/file-instance.xml
#canal.instance.global.spring.xml = classpath:spring/default-instance.xml

#################################################  
## mysql serverId  
canal.instance.mysql.slaveId = 1234  

# position info,需要改成自己的資料庫資訊  
canal.instance.master.address = 127.0.0.1:3306   
canal.instance.master.journal.name =
canal.instance.master.position =
canal.instance.master.timestamp =

#canal.instance.standby.address =   
#canal.instance.standby.journal.name =  
#canal.instance.standby.position =   
#canal.instance.standby.timestamp =   

# username/password,需要改成自己的資料庫資訊  
canal.instance.dbUsername = root
canal.instance.dbPassword = 123456
canal.instance.defaultDatabaseName = datamip  
canal.instance.connectionCharset = UTF-8  

# table regex  
canal.instance.filter.regex = .*\\..*  

#################################################

複製程式碼

    由於是全域性性的配置,所以上面三處標紅的地方要注意一下:

canal.port= 11111                 當前canal的伺服器埠號

canal.destinations= example      當前預設開啟了一個名為example的instance例項,如果想開多個instance,用","逗號隔開就可以了。。。

canal.instance.filter.regex = .*\\..*    mysql例項下的所有db的所有表都在監控範圍內。

《2》 instance.properties

      這個就是具體的某個instances例項的配置,未涉及到的配置都會從canal.properties上繼承。

複製程式碼

#################################################
## mysql serverId
canal.instance.mysql.slaveId = 1234

# position info
canal.instance.master.address = 192.168.23.1:3306
canal.instance.master.journal.name =
canal.instance.master.position =
canal.instance.master.timestamp =

#canal.instance.standby.address = 
#canal.instance.standby.journal.name =
#canal.instance.standby.position = 
#canal.instance.standby.timestamp = 

# username/password
canal.instance.dbUsername = canal
canal.instance.dbPassword = canal
canal.instance.defaultDatabaseName =datamip
canal.instance.connectionCharset = UTF-8

# table regex
canal.instance.filter.regex = .*\\..*
# table black regex
canal.instance.filter.black.regex =

#################################################

複製程式碼

    上面標紅的地方注意下就好了,去偷binlog的時候,需要知道的mysql地址和使用者名稱,密碼。

7. 開啟canal

      大家要記得把/canal/bin 目錄配置到 /etc/profile 的 Path中,方便快速開啟,通過下圖你會看到11111埠已經在centos上開啟了。

複製程式碼

[[email protected] bin]# ls
canal.pid  startup.bat  startup.sh  stop.sh
[[email protected] bin]# pwd
/usr/myapp/canal/bin
[[email protected] example]# startup.sh
cd to /usr/myapp/canal/bin for workaround relative path
LOG CONFIGURATION : /usr/myapp/canal/bin/../conf/logback.xml
canal conf : /usr/myapp/canal/bin/../conf/canal.properties
CLASSPATH :/usr/myapp/canal/bin/../conf:/usr/myapp/canal/bin/../lib/zookeeper-3.4.5.jar:/usr/myapp/canal/bin/../lib/zkclient-0.1.jar:/usr/myapp/canal/bin/../lib/spring-2.5.6.jar:/usr/myapp/canal/bin/../lib/slf4j-api-1.7.12.jar:/usr/myapp/canal/bin/../lib/protobuf-java-2.6.1.jar:/usr/myapp/canal/bin/../lib/oro-2.0.8.jar:/usr/myapp/canal/bin/../lib/netty-all-4.1.6.Final.jar:/usr/myapp/canal/bin/../lib/netty-3.2.5.Final.jar:/usr/myapp/canal/bin/../lib/logback-core-1.1.3.jar:/usr/myapp/canal/bin/../lib/logback-classic-1.1.3.jar:/usr/myapp/canal/bin/../lib/log4j-1.2.14.jar:/usr/myapp/canal/bin/../lib/jcl-over-slf4j-1.7.12.jar:/usr/myapp/canal/bin/../lib/guava-18.0.jar:/usr/myapp/canal/bin/../lib/fastjson-1.2.28.jar:/usr/myapp/canal/bin/../lib/commons-logging-1.1.1.jar:/usr/myapp/canal/bin/../lib/commons-lang-2.6.jar:/usr/myapp/canal/bin/../lib/commons-io-2.4.jar:/usr/myapp/canal/bin/../lib/commons-beanutils-1.8.2.jar:/usr/myapp/canal/bin/../lib/canal.store-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.sink-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.server-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.protocol-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.parse.driver-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.parse.dbsync-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.parse-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.meta-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.instance.spring-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.instance.manager-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.instance.core-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.filter-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.deployer-1.0.24.jar:/usr/myapp/canal/bin/../lib/canal.common-1.0.24.jar:/usr/myapp/canal/bin/../lib/aviator-2.2.1.jar:
cd to /usr/myapp/canal/conf/example for continue
[[email protected] example]# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:11111           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN     
tcp6       0      0 :::111                  :::*                    LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 ::1:631                 :::*                    LISTEN     
tcp6       0      0 ::1:25                  :::*                    LISTEN     
[[email protected] example]# 

複製程式碼

8. Java Client 程式碼

   canal driver 需要在maven倉庫中獲取一下:http://www.mvnrepository.com/artifact/com.alibaba.otter/canal.client/1.0.24,不過依賴還是蠻多的。

        <!-- https://mvnrepository.com/artifact/com.alibaba.otter/canal.client -->
        <dependency>
            <groupId>com.alibaba.otter</groupId>
            <artifactId>canal.client</artifactId>
            <version>1.0.24</version>
        </dependency>

9. 啟動java程式碼進行驗證

      下面的程式碼對table的CURD都做了一個基本的判斷,看看是不是能夠智慧感知,然後可以根據實際情況進行redis的更新操作。。。

複製程式碼

package com.datamip.canal;

import java.awt.Event;
import java.net.InetSocketAddress;
import java.util.List;

import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry.Column;
import com.alibaba.otter.canal.protocol.CanalEntry.Entry;
import com.alibaba.otter.canal.protocol.CanalEntry.EntryType;
import com.alibaba.otter.canal.protocol.CanalEntry.EventType;
import com.alibaba.otter.canal.protocol.CanalEntry.Header;
import com.alibaba.otter.canal.protocol.CanalEntry.RowChange;
import com.alibaba.otter.canal.protocol.Message;
import com.google.protobuf.InvalidProtocolBufferException;

public class App {

    public static void main(String[] args) throws InterruptedException {

        // 第一步:與canal進行連線
        CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("192.168.23.170", 11111),
                "example", "", "");
        connector.connect();

        // 第二步:開啟訂閱
        connector.subscribe();

        // 第三步:迴圈訂閱
        while (true) {
            try {
                // 每次讀取 1000 條
                Message message = connector.getWithoutAck(1000);

                long batchID = message.getId();

                int size = message.getEntries().size();

                if (batchID == -1 || size == 0) {
                    System.out.println("當前暫時沒有資料");
                    Thread.sleep(1000); // 沒有資料
                } else {
                    System.out.println("-------------------------- 有資料啦 -----------------------");
                    PrintEntry(message.getEntries());
                }

                // position id ack (方便處理下一條)
                connector.ack(batchID);

            } catch (Exception e) {
                // TODO: handle exception

            } finally {
                Thread.sleep(1000);
            }
        }
    }

    // 獲取每條列印的記錄
    @SuppressWarnings("static-access")
    public static void PrintEntry(List<Entry> entrys) {

        for (Entry entry : entrys) {

            // 第一步:拆解entry 實體
            Header header = entry.getHeader();
            EntryType entryType = entry.getEntryType();

            // 第二步: 如果當前是RowData,那就是我需要的資料
            if (entryType == EntryType.ROWDATA) {

                String tableName = header.getTableName();
                String schemaName = header.getSchemaName();

                RowChange rowChange = null;

                try {
                    rowChange = RowChange.parseFrom(entry.getStoreValue());
                } catch (InvalidProtocolBufferException e) {
                    e.printStackTrace();
                }

                EventType eventType = rowChange.getEventType();

                System.out.println(String.format("當前正在操作 %s.%s, Action= %s", schemaName, tableName, eventType));

                // 如果是‘查詢’ 或者 是 ‘DDL’ 操作,那麼sql直接打出來
                if (eventType == EventType.QUERY || rowChange.getIsDdl()) {
                    System.out.println("rowchange sql ----->" + rowChange.getSql());
                    return;
                }

                // 第三步:追蹤到 columns 級別
                rowChange.getRowDatasList().forEach((rowData) -> {

                    // 獲取更新之前的column情況
                    List<Column> beforeColumns = rowData.getBeforeColumnsList();

                    // 獲取更新之後的 column 情況
                    List<Column> afterColumns = rowData.getAfterColumnsList();

                    // 當前執行的是 刪除操作
                    if (eventType == EventType.DELETE) {
                        PrintColumn(beforeColumns);
                    }

                    // 當前執行的是 插入操作
                    if (eventType == eventType.INSERT) {
                        PrintColumn(afterColumns);
                    }

                    // 當前執行的是 更新操作
                    if (eventType == eventType.UPDATE) {
                        PrintColumn(afterColumns);
                    }
                });
            }
        }
    }

    // 每個row上面的每一個column 的更改情況
    public static void PrintColumn(List<Column> columns) {

        columns.forEach((column) -> {

            String columnName = column.getName();
            String columnValue = column.getValue();
            String columnType = column.getMysqlType();
            boolean isUpdated = column.getUpdated(); // 判斷 該欄位是否更新

            System.out.println(String.format("columnName=%s, columnValue=%s, columnType=%s, isUpdated=%s", columnName,
                    columnValue, columnType, isUpdated));

        });

    }
}

複製程式碼

<1> Update操作

<2> Insert操作

<3> Delete 操作

     從結果中看,沒毛病,有圖有真相,好了,本篇就說到這裡,對於開發的你,肯定是有幫助的~~~

相關推薦

快取一致性伺服器查詢資料解決方案canal

當你的專案資料量上去了之後,通常會遇到兩種情況,第一種情況應是最大可能的使用cache來對抗上層的高併發,第二種情況同樣也是需要使用分庫 分表對抗上層的高併發。。。逼逼逼起來容易,做起來並不那麼樂觀,由此引入的問題,不見得你有好的解決方案,下面就具體分享下。 一:儘可

數據解決方案緩存一致性服務器查詢

cati 如何 java.net meta mixed 解壓 -m tar 都是 緩存一致性和跨服務器查詢的數據異構解決方案canal   當你的項目數據量上去了之後,通常會遇到兩種情況,第一種情況應是最大可能的使用cache來對抗上層的高並發,第二種情

伺服器查詢資料

use master; go drop database mydata; go create database mydata; go use mydata; go create table t_user ( userguid uniqueidentifier not null defa

mysql實現伺服器查詢資料

在日常的開發中經常進行跨資料庫進行查詢資料。 同伺服器下跨資料庫進行查詢在表前加上資料庫名就可以查詢到資料。 mysql跨伺服器進行查詢提供了FEDERATED引擎進行對映表,然後進行查詢。 mysql資料庫federated引擎是關閉的,首先需要先啟用該引擎。

sqlserver中伺服器查詢資料

[SQL SERVER] 跨伺服器查詢 方法一: 用OPENDATASOURCE 下面是個跨SQLServer查詢的示例 Select TableA.*,TableB.* From OPENDATASOURCE(          'SQLOLEDB',         

sql serve 伺服器查詢資料方法

 今天在做sql server 的資料查詢時,需要用到跨伺服器連線,在這裡記錄一下,如何在sql server 中,使用跨伺服器查詢的方法,有以下步驟。 /*建立中間資料庫連結 exec sp_addlinkedserver 'MiddleData', ' ', 'SQ

伺服器匯入資料查詢資料

跨伺服器匯入資料SQL語句及其問題解決方案 跨伺服器匯入資料SQL語句: --自定義表名,在匯入前建立表SELECT * INTO TbName FROM OPENROWSET('SQLOLEDB','192.168.0.7';'sa';'damon king',DBName

關於vue-cliaxsios的使用域訪問資料的總結

一、安裝axsois   1.安裝:在vue-cli根目錄下安裝axsois    2.更改原型鏈方法:在main.js下更改:   3.在元件中使用: 二、跨域   1.在config/index.js 新增如下程式碼: proxyTable: { './api':{ targ

如何使用ajax實現頁面資料儲存修改根據條件查詢資料

*今天我們來講講ajax實現儲存和修改,其實很簡單,跟上期的刪除方法相似,* *好了,廢話不多說,直接上程式碼* 注意:這裡麵包含了儲存方法,修改,和條件查詢及對select下拉列表的操作,請仔細看完 功能頁面Jsp <%@ page lan

【4】Java併發程式設計:多執行緒中的快取一致性CAS

一、匯流排鎖定和快取一致性 基本概念 這是兩個作業系統層面的概念。隨著多核時代的到來,併發操作已經成了很正常的現象,作業系統必須要有一些機制和原語,以保證某些基本操作的原子性,比如處理器需要保證讀一個位元組或寫一個位元組是原子的,那麼它是如何實現的呢?有

Java的多執行緒機制:快取一致性CAS

一、匯流排鎖定和快取一致性 這是兩個作業系統層面的概念。隨著多核時代的到來,併發操作已經成了很正常的現象,作業系統必須要有一些機制和原語,以保證某些基本操作的原子性,比如處理器需要保證讀一個位元組或寫一個位元組是原子的,那麼它是如何實現的呢?有兩種機制:匯流排鎖定和快取

JSONP操作01_本地訪問資料域訪問資料

1.jsonp簡介 json 是一種資料格式 jsonp 是一種資料呼叫的方式。 1)什麼是jsonp 為了便於客戶端使用資料,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP,該協議的一個要點就是允許使用者傳遞一個callback引數給服務端,然後服務端返回資料時會將

jdbc插入更新、查詢資料

jdbc插入資料 /**** * 新增單任務執行記錄 */ @Override public void insertSingleJobLog(ScheduleJobBatchLogDTO sin

MS SQLSERVER如何實現伺服器查詢

--跨伺服器查詢如下: SELECT a.* FROM OPENROWSET('MSDASQL',    'DRIVER={SQL Server};SERVER=10.27.27.160;UID=sa;PWD=ncunicom_alarm',    BSC_ALARM.dbo.ALARM_LIS

SQL SERVER伺服器查詢

1.執行儲存過程 sp_addlinkedserver 以將伺服器新增到 sys.servers。 exec sp_addlinkedserver 'IPTV', ' ', 'SQLOLEDB ', '遠端伺服器名或ip地址 ' exec sp_addlink

Oracle資料庫查詢資料-使用Oracle的Database Link進行資料庫操作

有這麼一個需求,要搭建測試環境,需要把開發庫中的一部分表和資料匯入到測試庫中。咋一看這個需求有很多的實現方法,至少可以使用Oracle的匯入匯出來操作。這肯定能夠實現,但感覺比較low,下面來看一種高大上的做法,使用Oracle的DATABASE LINK。 DATABAS

Android客戶端伺服器交換資料的一種方案

由於很多因素使得客戶端和伺服器之間互動的一些資料都要經過加密,為了方便,很多使用非對稱的加密演算法進行加密,其中RSA演算法成為首選。下面說說在Android客戶端怎中怎麼應用這種加密方案。 首先在我們Android客戶端啟動應用程式的時候,我們先請求一個伺服器,讓服務將R

mysql 通過federated引擎 伺服器訪問資料

首先檢查本地mysql資料庫是否支援federated引擎, 如圖所示, 執行 show engines; 如圖所示: 說明不支援。 然後找到安裝目錄下的my.ini檔案,開啟編輯。 在[mysqld]  下面新增一行  federated   儲存即可。如果沒有[mysq

Sql 伺服器訪問資料

----開啟伺服器資料庫exec sp_configure 'show advanced options',1reconfigureexec sp_configure 'Ad Hoc Distributed Queries',1reconfigure--訪問資料庫(可以進行資

HttpClient下載圖片伺服器提交資料例項

使用 HttpClient 需要以下 6 個步驟: 1. 建立 HttpClient 的例項 2. 建立某種連線方法的例項,在這裡是GetMethod。在 GetMethod 的建構函式中傳入待連線的