Search in sources :

Example 41 with LogPosition

use of com.alibaba.otter.canal.protocol.position.LogPosition in project canal by alibaba.

the class FileMixedMetaManager method start.

public void start() {
    super.start();
    Assert.notNull(dataDir);
    if (!dataDir.exists()) {
        try {
            FileUtils.forceMkdir(dataDir);
        } catch (IOException e) {
            throw new CanalMetaManagerException(e);
        }
    }
    if (!dataDir.canRead() || !dataDir.canWrite()) {
        throw new CanalMetaManagerException("dir[" + dataDir.getPath() + "] can not read/write");
    }
    dataFileCaches = MigrateMap.makeComputingMap(this::getDataFile);
    executor = Executors.newScheduledThreadPool(1);
    destinations = MigrateMap.makeComputingMap(this::loadClientIdentity);
    cursors = MigrateMap.makeComputingMap(clientIdentity -> {
        Position position = loadCursor(clientIdentity.getDestination(), clientIdentity);
        if (position == null) {
            // 返回一个空对象标识,避免出现异常
            return nullCursor;
        } else {
            return position;
        }
    });
    updateCursorTasks = Collections.synchronizedSet(new HashSet<>());
    // 启动定时工作任务
    executor.scheduleAtFixedRate(() -> {
        List<ClientIdentity> tasks = new ArrayList<>(updateCursorTasks);
        for (ClientIdentity clientIdentity : tasks) {
            MDC.put("destination", String.valueOf(clientIdentity.getDestination()));
            try {
                updateCursorTasks.remove(clientIdentity);
                // 定时将内存中的最新值刷到file中,多次变更只刷一次
                if (logger.isInfoEnabled()) {
                    LogPosition cursor = (LogPosition) getCursor(clientIdentity);
                    logger.info("clientId:{} cursor:[{},{},{},{},{}] address[{}]", clientIdentity.getClientId(), cursor.getPostion().getJournalName(), cursor.getPostion().getPosition(), cursor.getPostion().getTimestamp(), cursor.getPostion().getServerId(), cursor.getPostion().getGtid(), cursor.getIdentity().getSourceAddress().toString());
                }
                flushDataToFile(clientIdentity.getDestination());
            } catch (Throwable e) {
                // ignore
                logger.error("period update" + clientIdentity.toString() + " curosr failed!", e);
            }
        }
    }, period, period, TimeUnit.MILLISECONDS);
}
Also used : LoggerFactory(org.slf4j.LoggerFactory) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Lists(com.google.common.collect.Lists) Charset(java.nio.charset.Charset) JsonUtils(com.alibaba.otter.canal.common.utils.JsonUtils) Map(java.util.Map) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) CanalMetaManagerException(com.alibaba.otter.canal.meta.exception.CanalMetaManagerException) Position(com.alibaba.otter.canal.protocol.position.Position) Logger(org.slf4j.Logger) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition) Set(java.util.Set) IOException(java.io.IOException) FileUtils(org.apache.commons.io.FileUtils) File(java.io.File) StandardCharsets(java.nio.charset.StandardCharsets) Executors(java.util.concurrent.Executors) MigrateMap(com.google.common.collect.MigrateMap) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) ClientIdentity(com.alibaba.otter.canal.protocol.ClientIdentity) MDC(org.slf4j.MDC) Collections(java.util.Collections) Assert(org.springframework.util.Assert) ClientIdentity(com.alibaba.otter.canal.protocol.ClientIdentity) Position(com.alibaba.otter.canal.protocol.position.Position) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition) ArrayList(java.util.ArrayList) CanalMetaManagerException(com.alibaba.otter.canal.meta.exception.CanalMetaManagerException) IOException(java.io.IOException) HashSet(java.util.HashSet) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Example 42 with LogPosition

use of com.alibaba.otter.canal.protocol.position.LogPosition in project canal by alibaba.

the class AbstractEventParser method buildLastPosition.

protected LogPosition buildLastPosition(CanalEntry.Entry entry) {
    // 初始化一下
    LogPosition logPosition = new LogPosition();
    EntryPosition position = new EntryPosition();
    position.setJournalName(entry.getHeader().getLogfileName());
    position.setPosition(entry.getHeader().getLogfileOffset());
    position.setTimestamp(entry.getHeader().getExecuteTime());
    // add serverId at 2016-06-28
    position.setServerId(entry.getHeader().getServerId());
    // set gtid
    position.setGtid(entry.getHeader().getGtid());
    logPosition.setPostion(position);
    LogIdentity identity = new LogIdentity(runningInfo.getAddress(), -1L);
    logPosition.setIdentity(identity);
    return logPosition;
}
Also used : LogIdentity(com.alibaba.otter.canal.protocol.position.LogIdentity) EntryPosition(com.alibaba.otter.canal.protocol.position.EntryPosition) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Example 43 with LogPosition

use of com.alibaba.otter.canal.protocol.position.LogPosition in project canal by alibaba.

the class CanalServerWithEmbedded method get.

/**
 * 获取数据,可以指定超时时间.
 *
 * <pre>
 * 几种case:
 * a. 如果timeout为null,则采用tryGet方式,即时获取
 * b. 如果timeout不为null
 *    1. timeout为0,则采用get阻塞方式,获取数据,不设置超时,直到有足够的batchSize数据才返回
 *    2. timeout不为0,则采用get+timeout方式,获取数据,超时还没有batchSize足够的数据,有多少返回多少
 *
 * 注意: meta获取和数据的获取需要保证顺序性,优先拿到meta的,一定也会是优先拿到数据,所以需要加同步. (不能出现先拿到meta,拿到第二批数据,这样就会导致数据顺序性出现问题)
 * </pre>
 */
@Override
public Message get(ClientIdentity clientIdentity, int batchSize, Long timeout, TimeUnit unit) throws CanalServerException {
    checkStart(clientIdentity.getDestination());
    checkSubscribe(clientIdentity);
    CanalInstance canalInstance = canalInstances.get(clientIdentity.getDestination());
    synchronized (canalInstance) {
        // 获取到流式数据中的最后一批获取的位置
        PositionRange<LogPosition> positionRanges = canalInstance.getMetaManager().getLastestBatch(clientIdentity);
        if (positionRanges != null) {
            throw new CanalServerException(String.format("clientId:%s has last batch:[%s] isn't ack , maybe loss data", clientIdentity.getClientId(), positionRanges));
        }
        Events<Event> events = null;
        Position start = canalInstance.getMetaManager().getCursor(clientIdentity);
        events = getEvents(canalInstance.getEventStore(), start, batchSize, timeout, unit);
        if (CollectionUtils.isEmpty(events.getEvents())) {
            logger.debug("get successfully, clientId:{} batchSize:{} but result is null", clientIdentity.getClientId(), batchSize);
            // 返回空包,避免生成batchId,浪费性能
            return new Message(-1, true, new ArrayList());
        } else {
            // 记录到流式信息
            Long batchId = canalInstance.getMetaManager().addBatch(clientIdentity, events.getPositionRange());
            boolean raw = isRaw(canalInstance.getEventStore());
            List entrys = null;
            if (raw) {
                entrys = Lists.transform(events.getEvents(), Event::getRawEntry);
            } else {
                entrys = Lists.transform(events.getEvents(), Event::getEntry);
            }
            if (logger.isInfoEnabled()) {
                logger.info("get successfully, clientId:{} batchSize:{} real size is {} and result is [batchId:{} , position:{}]", clientIdentity.getClientId(), batchSize, entrys.size(), batchId, events.getPositionRange());
            }
            // 直接提交ack
            ack(clientIdentity, batchId);
            return new Message(batchId, raw, entrys);
        }
    }
}
Also used : CanalInstance(com.alibaba.otter.canal.instance.core.CanalInstance) Message(com.alibaba.otter.canal.protocol.Message) Position(com.alibaba.otter.canal.protocol.position.Position) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition) ArrayList(java.util.ArrayList) Event(com.alibaba.otter.canal.store.model.Event) ArrayList(java.util.ArrayList) List(java.util.List) CanalServerException(com.alibaba.otter.canal.server.exception.CanalServerException) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Example 44 with LogPosition

use of com.alibaba.otter.canal.protocol.position.LogPosition in project canal by alibaba.

the class AbstractCanalStoreScavenge method getLatestAckPosition.

/**
 * 找出该destination中可被清理掉的position位置
 *
 * @param destination
 */
private Position getLatestAckPosition(String destination) {
    List<ClientIdentity> clientIdentitys = canalMetaManager.listAllSubscribeInfo(destination);
    LogPosition result = null;
    if (!CollectionUtils.isEmpty(clientIdentitys)) {
        // 尝试找到一个最小的logPosition
        for (ClientIdentity clientIdentity : clientIdentitys) {
            LogPosition position = (LogPosition) canalMetaManager.getCursor(clientIdentity);
            if (position == null) {
                continue;
            }
            if (result == null) {
                result = position;
            } else {
                result = min(result, position);
            }
        }
    }
    return result;
}
Also used : ClientIdentity(com.alibaba.otter.canal.protocol.ClientIdentity) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Example 45 with LogPosition

use of com.alibaba.otter.canal.protocol.position.LogPosition in project canal by alibaba.

the class MemoryEventStoreWithBuffer method cleanUntil.

public void cleanUntil(Position position, Long seqId) throws CanalStoreException {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        long sequence = ackSequence.get();
        long maxSequence = getSequence.get();
        boolean hasMatch = false;
        long memsize = 0;
        // ack没有list,但有已存在的foreach,还是节省一下list的开销
        long localExecTime = 0L;
        int deltaRows = 0;
        if (seqId > 0) {
            maxSequence = seqId;
        }
        for (long next = sequence + 1; next <= maxSequence; next++) {
            Event event = entries[getIndex(next)];
            if (localExecTime == 0 && event.getExecuteTime() > 0) {
                localExecTime = event.getExecuteTime();
            }
            deltaRows += event.getRowsCount();
            memsize += calculateSize(event);
            if ((seqId < 0 || next == seqId) && CanalEventUtils.checkPosition(event, (LogPosition) position)) {
                // 找到对应的position,更新ack seq
                hasMatch = true;
                if (batchMode.isMemSize()) {
                    ackMemSize.addAndGet(memsize);
                    // 尝试清空buffer中的内存,将ack之前的内存全部释放掉
                    for (long index = sequence + 1; index < next; index++) {
                        // 设置为null
                        entries[getIndex(index)] = null;
                    }
                    // 考虑getFirstPosition/getLastPosition会获取最后一次ack的position信息
                    // ack清理的时候只处理entry=null,释放内存
                    Event lastEvent = entries[getIndex(next)];
                    lastEvent.setEntry(null);
                    lastEvent.setRawEntry(null);
                }
                if (ackSequence.compareAndSet(sequence, next)) {
                    // 避免并发ack
                    notFull.signal();
                    ackTableRows.addAndGet(deltaRows);
                    if (localExecTime > 0) {
                        ackExecTime.lazySet(localExecTime);
                    }
                    return;
                }
            }
        }
        if (!hasMatch) {
            // 找不到对应需要ack的position
            throw new CanalStoreException("no match ack position" + position.toString());
        }
    } finally {
        lock.unlock();
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) Event(com.alibaba.otter.canal.store.model.Event) CanalStoreException(com.alibaba.otter.canal.store.CanalStoreException) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Aggregations

LogPosition (com.alibaba.otter.canal.protocol.position.LogPosition)46 EntryPosition (com.alibaba.otter.canal.protocol.position.EntryPosition)24 List (java.util.List)16 InetSocketAddress (java.net.InetSocketAddress)15 Test (org.junit.Test)15 AbstractLogPositionManager (com.alibaba.otter.canal.parse.index.AbstractLogPositionManager)13 CanalSinkException (com.alibaba.otter.canal.sink.exception.CanalSinkException)12 AbstractCanalEventSinkTest (com.alibaba.otter.canal.parse.stub.AbstractCanalEventSinkTest)11 Entry (com.alibaba.otter.canal.protocol.CanalEntry.Entry)11 AtomicLong (java.util.concurrent.atomic.AtomicLong)10 CanalParseException (com.alibaba.otter.canal.parse.exception.CanalParseException)9 TimeoutChecker (com.alibaba.otter.canal.parse.helper.TimeoutChecker)8 CanalEntry (com.alibaba.otter.canal.protocol.CanalEntry)6 IOException (java.io.IOException)6 ClientIdentity (com.alibaba.otter.canal.protocol.ClientIdentity)5 LogIdentity (com.alibaba.otter.canal.protocol.position.LogIdentity)5 ArrayList (java.util.ArrayList)5 Date (java.util.Date)5 CanalInstance (com.alibaba.otter.canal.instance.core.CanalInstance)4 AuthenticationInfo (com.alibaba.otter.canal.parse.support.AuthenticationInfo)4