Можно ли рекомендовать базу данных, которая масштабируется горизонтально? [закрытый]

Четырехугольное преобразование

. Один из способов сделать это - использовать четырехугольные преобразования. Они отличаются от 3D-преобразований и позволяют рисовать на холсте, если вы хотите экспортировать результат.

Пример, показанный здесь, упрощен и использует базовые субдивизины и «читы» для рендеринга сам, то есть он рисует в небольшом квадрате вместо формы разделенной ячейки, но из-за небольшого размера и перекрытия мы можем избежать этого во многих случаях без крайностей.

Правильный способ состоял бы в том, чтобы разделить фигуру на два треугольника, затем сканировать пиксель в растровом изображении адресата, сопоставить точку от треугольника назначения до исходного треугольника. Если значение позиции было дробным, вы использовали бы это для определения интерполяции пикселей (f.ex. двухлинейный 2x2 или би-кубический 4x4).

Я не собираюсь покрывать все это в этом ответе, поскольку это быстро станет недоступным для формата SO, но этот метод, вероятно, будет подходящим в этом случае, если вам не нужно его анимировать (это недостаточно для этого, если вы хотите высокого разрешения).

Метод

Давайте начнем с начальной четырехсторонней формы:

Initial quad [/g10]

Первым шагом является интерполяция Y-позиций на каждом баре C1 -C4 и C2-C3. Нам нужна текущая позиция, а также следующая позиция. Для этого мы будем использовать линейную интерполяцию («lerp»), используя нормированное значение для t:

y1current = lerp( C1, C4, y / height)
y2current = lerp( C2, C3, y / height)

y1next = lerp(C1, C4, (y + step) / height)
y2next = lerp(C2, C3, (y + step) / height)

Это дает нам новую строку между и вдоль внешних вертикальных баров.

http://i.imgur.com/qAWUK4B.png [/g11]

Далее нам нужны позиции X на этой строке, как текущей, так и следующей. Это даст нам четыре позиции, которые мы будем заполнять текущим пикселем, либо как-есть, либо интерполировать его (здесь не показано):

p1 = lerp(y1current, y2current, x / width)
p2 = lerp(y1current, y2current, (x + step) / width)
p3 = lerp(y1next, y2next, (x + step) / width)
p4 = lerp(y1next, y2next, x / width)

x и y будет позицией в источнике изображение с использованием целых значений.

Iterating x/y [/g12]

Мы можем использовать эту настройку внутри цикла, который будет перебирать каждый пиксель в исходном растровом изображении.

Демо

Демо можно найти в нижней части ответа. Переместите круговые ручки вокруг, чтобы преобразовать и воспроизвести с помощью значения шага, чтобы увидеть его влияние на производительность и результат.

Демонстрация будет иметь муар и другие артефакты, но, как упоминалось ранее,

Снимок из демонстрации:

Demo snapshot [/g13]

Альтернативные методы

Вы также можете использовать WebGL или Three.js для настройки 3D-среды и рендеринга на холст. Вот ссылка на последнее решение:

и пример того, как использовать текстурированную поверхность :

Используя это подход позволит вам экспортировать результат на холст или изображение, но для производительности требуется GPU на клиенте.

Если вам не нужно экспортировать или манипулировать результатом, я бы предложил для использования простого CSS 3D-преобразования, как показано в других ответах.

/* Quadrilateral Transform - (c) Ken Nilsen, CC3.0-Attr */
var img = new Image();  img.onload = go;
img.src = "https://i.imgur.com/EWoZkZm.jpg";

function go() {
  var me = this,
      stepEl = document.querySelector("input"),
      stepTxt = document.querySelector("span"),
      c = document.querySelector("canvas"),
      ctx = c.getContext("2d"),
      corners = [
        {x: 100, y: 20},           // ul
        {x: 520, y: 20},           // ur
        {x: 520, y: 380},          // br
        {x: 100, y: 380}           // bl
      ],
      radius = 10, cPoint, timer,  // for mouse handling
      step = 4;                    // resolution

  update();

  // render image to quad using current settings
  function render() {
		
    var p1, p2, p3, p4, y1c, y2c, y1n, y2n,
        w = img.width - 1,         // -1 to give room for the "next" points
        h = img.height - 1;

    ctx.clearRect(0, 0, c.width, c.height);

    for(y = 0; y < h; y += step) {
      for(x = 0; x < w; x += step) {
        y1c = lerp(corners[0], corners[3],  y / h);
        y2c = lerp(corners[1], corners[2],  y / h);
        y1n = lerp(corners[0], corners[3], (y + step) / h);
        y2n = lerp(corners[1], corners[2], (y + step) / h);

        // corners of the new sub-divided cell p1 (ul) -> p2 (ur) -> p3 (br) -> p4 (bl)
        p1 = lerp(y1c, y2c,  x / w);
        p2 = lerp(y1c, y2c, (x + step) / w);
        p3 = lerp(y1n, y2n, (x + step) / w);
        p4 = lerp(y1n, y2n,  x / w);

        ctx.drawImage(img, x, y, step, step,  p1.x, p1.y, // get most coverage for w/h:
            Math.ceil(Math.max(step, Math.abs(p2.x - p1.x), Math.abs(p4.x - p3.x))) + 1,
            Math.ceil(Math.max(step, Math.abs(p1.y - p4.y), Math.abs(p2.y - p3.y))) + 1)
      }
    }
  }
  
  function lerp(p1, p2, t) {
    return {
      x: p1.x + (p2.x - p1.x) * t, 
      y: p1.y + (p2.y - p1.y) * t}
  }

  /* Stuff for demo: -----------------*/
  function drawCorners() {
    ctx.strokeStyle = "#09f"; 
    ctx.lineWidth = 2;
    ctx.beginPath();
    // border
    for(var i = 0, p; p = corners[i++];) ctx[i ? "lineTo" : "moveTo"](p.x, p.y);
    ctx.closePath();
    // circular handles
    for(i = 0; p = corners[i++];) {
      ctx.moveTo(p.x + radius, p.y); 
      ctx.arc(p.x, p.y, radius, 0, 6.28);
    }
    ctx.stroke()
  }
	
  function getXY(e) {
    var r = c.getBoundingClientRect();
    return {x: e.clientX - r.left, y: e.clientY - r.top}
  }
	
  function inCircle(p, pos) {
    var dx = pos.x - p.x,
        dy = pos.y - p.y;
    return dx*dx + dy*dy <= radius * radius
  }

  // handle mouse
  c.onmousedown = function(e) {
    var pos = getXY(e);
    for(var i = 0, p; p = corners[i++];) {if (inCircle(p, pos)) {cPoint = p; break}}
  }
  window.onmousemove = function(e) {
    if (cPoint) {
      var pos = getXY(e);
      cPoint.x = pos.x; cPoint.y = pos.y;
      cancelAnimationFrame(timer);
      timer = requestAnimationFrame(update.bind(me))
    }
  }
  window.onmouseup = function() {cPoint = null}
  
  stepEl.oninput = function() {
    stepTxt.innerHTML = (step = Math.pow(2, +this.value));
    update();
  }
  
  function update() {render(); drawCorners()}
}
body {margin:20px;font:16px sans-serif}
canvas {border:1px solid #000;margin-top:10px}
4
13
задан Mark Harrison 10 May 2016 в 04:36
поделиться

11 ответов

Не волнуйтесь, хорошие решения прибывают!

Couchdb и Hypertable являются открытым исходным кодом и все еще в альфе, но они ясно разработаны для создания масштабирования на товарном программном обеспечении простым. Они работают вполне прилично и могут измениться, как Вы думаете о базах данных.

Кроме того, если это должно хорошо позволить кому-то еще сделать распределение для Вас, Google AppEngine и Amazon SimpleDB является чрезвычайно дешевыми сервисами распределенной базы данных, хотя они оба в бета-версии прямо сейчас, таким образом, строгие ограничения наложены.

4
ответ дан 1 December 2019 в 21:25
поделиться

Oracle RAС - Реальный кластер приложения

Это работает приятно, Вы просто добавляете поля к своему кластеру. Можно заменить от одного поля до другого. Это не репликация, все поля являются частью той же логической единицы.

Это - симпатичный spendy, конечно.

5
ответ дан 1 December 2019 в 21:25
поделиться

Существуют методы устройства хранения данных, такие как JavaSpaces (или коммерческая реализация, такие как Gigaspaces), которые обеспечивают хорошо масштабируемый, быстрый и безопасный доступ к объектам.

Там также распределяются cacheing системы, такие как memcached, которые предлагают аналогичный подход.

Конечно, ни один из них истинные базы данных, но они - вещи, которые могут работать в сочетании с базами данных для предложения большой суммы горизонтальной масштабируемости, учитывая подходящую архитектуру. Настоящая проблема состоит в том, что, если Вы хотите все совершенство ACID, которое идет с базой данных, существуют определенные неизбежные потери производительности. Единственный выход должен выяснить биты, где Вы не нуждаетесь в ACID и используете другие технологии для обслуживания тех битов.

2
ответ дан 1 December 2019 в 21:25
поделиться

Oracle RAС является Роллс-ройс баз данных, позволяющих узлы дополнительного оборудования быть добавленными относительно легко и аппаратная обработка отказа.

Однако Ваши затраты потребительского оборудования затмятся стоимостью лицензии.

Почему dod Вы чувствуете, что Вам нужно горизонтальное масштабирование. Много сервер ядра процессора с 40 ГБ RAM и устройства хранения данных SAN может поддерживать очень большую установку DB.

Можно ли предоставить какую-либо калибровку и ожидаемую информацию о действии, чтобы позволить лучше понимать проблемы?

2
ответ дан 1 December 2019 в 21:25
поделиться

При потере работоспособности по маршруту RAC, стоит помнить, что это не масштабируется горизонтально навсегда. Даже парни продаж признают, что 90% rac клиентов являются 4 узлами или меньше. После того как Вы идете больше, чем это, Вы получаете убывающую доходность. Таким образом, rac может работать на Вас, но он, как гарантируют, не будет ответом.

2
ответ дан 1 December 2019 в 21:25
поделиться

Netezza и другие datawarehouse устройства масштабируют этот путь, но они не хороши для рабочих нагрузок веб-приложения и OLTP.

1
ответ дан 1 December 2019 в 21:25
поделиться

MySQL: http://www.mysql.com/why-mysql/scaleout.html

Ограничения - то, что это работает лучше всего с главным образом рабочими нагрузками чтения. У Вас обычно есть одно 'ведущее устройство', которое получает все записи и много 'ведомых устройств', которые копируют записи. Затем Вы распределяете чтения по всем базам данных.

Репликация MySQL является асинхронной, таким образом, необходимо будет, вероятно, иметь дело с проблемами задержки (Вы пишете в ведущее устройство и затем читаете из ведомого устройства, прежде чем запись копировалась).

2
ответ дан 1 December 2019 в 21:25
поделиться

Маршрут Oracle для масштабирования через несколько машин называют Реальными Кластерами Приложения (Oracle RAС). Нет никакого конца документации относительно этого в другом месте; Вы могли бы попытаться запуститься по http://www.oracle.com/database/rac_home.html.

1
ответ дан 1 December 2019 в 21:25
поделиться

Если Вы серьезно думаете, что будете масштабировать достойное многоядерное поле "Big Iron", то Вы думаете о разделении Ваших данных. Это - хороший, агностик базы данных способ масштабировать горизонтально.

Все базы данных, которые горизонтально прибудут в серьезную стоимость.

Если у Вас нет мега $$ для броска в проблему, забудьте о RAC. В то время как его очень хорошее, его ОЧЕНЬ дорогое, после того как Вы масштабируетесь вне 2 узлов.

0
ответ дан 1 December 2019 в 21:25
поделиться

Oracle Реальные Кластеры Приложения. Если Вы хотите лучшее, затем смотрят на него.

0
ответ дан 1 December 2019 в 21:25
поделиться

Oracle RAC вообще не масштабируется по горизонтали, потому что все экземпляры Oracle используют одно и то же хранилище данных. Да, с помощью SAN вы можете получить базу данных большого размера, но она вообще не масштабируется. Другими словами, Oracle RAC по-прежнему является подходом с возможностью масштабирования. Таким образом, для масштабирования по горизонтали или по горизонтали вы должны разделить данные по функциям, что означает размещение разных групп таблиц в разных базах данных; или разделите свои данные на таблицу, что означает разделение одной таблицы на несколько подтаблиц с одинаковой схемой, но хранящихся в разных базах данных. Таким образом, вы получаете масштабируемое решение. По этому поводу есть много ресурсов. Sharding некоторое время был модным словом в блогах об архитектуре веб-сайтов Web 2.0. Поскольку сегментирование не поддерживается напрямую самой базой данных, вам необходимо создать собственное решение. Но, как я сказал, уже есть много уроков. Для Oracle возможно разделение таблицы. Для mysql проверьте этот вопрос

7
ответ дан 1 December 2019 в 21:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: