要为VoxxedDays Ticino准备演示,我已经在Amazon Eks上使用Yugabytedb,开源分布式SQL创建了一个Kubernetes群集,如this post中安装了。
yugabytedb具有与Cassandra兼容的API(称为YCQL)和一个与后Ql兼容的API(称为YSQL)。如果您要为MongoDB编写应用程序,该应用程序要移至SQL数据库怎么办?您可能想将其重写以从SQL功能中受益,但是,您可以同时重新编写所有功能,而是可以在FerretDB上添加MongoDB兼容的API。
让我们将其添加到我的Kubernetes群集中。这是一个测试。 FerretDB仍在早期。但是,MongoDB代理和分布式SQL数据库的这种组合也许是将来是MongoDB或DocumentDB的开源替代方法。
运行连接到yugabytedb的ferretdb
为了测试这种可能性,我将使用ferretdb/ferretdb
映像whish whish运行ferretdb
启动一个吊舱。我使用--listen-addr
和--postgresql-url
的PostgreSQL连接设置了它的终点。3:
$ kubectl run --image ferretdb/ferretdb ferretdb -- \
--listen-addr=0.0.0.0:27017 \
--postgresql-url="postgres://yugabyte:yugabyte@yb-tservers.yb-demo-eu-west-1a.svc.cluster.local:5433/yugabyte"
pod/ferretdb created
它连接到clusterip服务yb-tservers
,该连接将连接分配到一个AZ eu-west-1a
中的所有Yugabytedb服务器。
我正在从mongosh
shell中进行测试:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ferretdb 1/1 Running 0 11m 192.168.50.78 ip-192-168-48-228.eu-west-1.compute.internal <none> <none>
$ kubectl run -it --rm --restart=Never --image mongo mongosh -- \
mongosh mongodb://192.168.50.78:27017/mongodb
我可以创建一个集合
mongodb> db.createCollection('demo');
{ ok: 1 }
在yugabytedb上创建相应的表:
我从吊舱中获得了IP地址。我将创建服务。
运行FerretDB Pods的负载平衡器
虽然代理会增加一些延迟。那么您可能需要想要更多的豆荚。我将稍后为其创建一个replicaset,但就目前而言,让我们创建一个载重器来提出这个想法:
$ kubectl expose pod ferretdb --port=27017 --target-port=27017 \
--name=ferretdb-service --type=LoadBalancer
service/ferretdb-service exposed
我可以通过此服务测试连接:
$ kubectl run -it --rm --restart=Never --image mongo mongosh -- \
mongosh mongodb://ferretdb-service.default.svc.cluster.local:27017/mongodb --quiet
If you don't see a command prompt, try pressing enter.
mongodb> show collections;
demo
mongodb>
我现在可以使用Internet的FerretDB端点,获取外部IP地址:
$ kubectl get services --field-selector "metadata.name=ferretdb-service" -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}'
abebf50dee88a462ab90d371dfdaa44f-1345053103.eu-west-1.elb.amazonaws.com
我可以通过笔记本电脑与mongosh
连接:
$ mongosh mongodb://abebf50dee88a462ab90d371dfdaa44f-1345053103.eu-west-1.elb.amazonaws.com:27017/mongodb --quiet
mongodb> db.demo.insertOne({ "message": "Hello World" });
{
acknowledged: true,
insertedId: ObjectId("63c85f7aa3db61ccd4324a04")
}
mongodb> db.demo.findOne();
{ _id: ObjectId("63c85f7aa3db61ccd4324a04"), message: 'Hello World' }
mongodb>
部署为replicaset
现在我已经通过手动创建吊舱和服务进行了测试,我将自动化。我删除了上面创建的那些:
$ kubectl delete service ferretdb-service
service "ferretdb-service" deleted
$ kubectl delete pod ferretdb
pod "ferretdb" deleted
这是ferretdb复制品的YAML声明:
cat > ferretdb-rs.yaml <<'YAML'
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: ferretdb
namespace: yb-demo-eu-west-1a
labels:
run: ferretdb
spec:
replicas: 3
selector:
matchLabels:
run: ferretdb
template:
metadata:
labels:
run: ferretdb
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- eu-west-1a
containers:
- name: ferretdb
image: ferretdb/ferretdb
args:
- --listen-addr=0.0.0.0:27017
- --postgresql-url=postgres://yugabyte:yugabyte@yb-tservers.yb-demo-eu-west-1a.svc.cluster.local:5433/yugabyte
YAML
kubectl apply -f ferretdb-rs.yaml
和LoadBalancer:
cat > ferretdb-lb.yaml <<'YAML'
apiVersion: v1
kind: Service
metadata:
name: ferretdb-service
namespace: yb-demo-eu-west-1a
labels:
run: ferretdb
spec:
type: LoadBalancer
selector:
run: ferretdb
ports:
- protocol: TCP
port: 27017
targetPort: 27017
YAML
kubectl apply -f ferretdb-lb.yaml
我已经在一个AZ(eu-west-1a
)中创建了它们,并连接到同一AZ中的Yugabytedb平板电脑服务器。
与Mongo或Postgres客户联系
我获得了mongoDB端点地址:
$ kubectl get services \
-o jsonpath='mongodb://{.items[0].status.loadBalancer.ingress[0].hostname}:{.items[0].spec.ports[0].port}/mongodb' \
--field-selector "metadata.name=ferretdb-service" \
-n yb-demo-eu-west-1a
mongodb://a4ee051c7cf844538b1bc90fbd3ef56a-565835635.eu-west-1.elb.amazonaws.com:27017/mongodb
使用此内容,我加载了一些示例数据:
$ curl -s https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/latest/owid-covid-latest.json |
jq -c ".[]" |
while read json
do
echo "db.covid.insertOne( $json )"
done | mongosh mongodb://a4ee051c7cf844538b1bc90fbd3ef56a-565835635.eu-west-1.elb.amazonaws.com:27017/mongodb
现在获取PostgreSQL DB地址:
$ kubectl get services \
-o jsonpath='postgres://{.items[0].status.loadBalancer.ingress[0].hostname}:{.items[0].spec.ports[?(@.name=="tcp-ysql-port")].port}/yugabyte' \
--field-selector "metadata.name=yb-tserver-service" \
-n yb-demo-eu-west-1a
postgres://a4ee051c7cf844538b1bc90fbd3ef56a-565835635.eu-west-1.elb.amazonaws.com:5433/yugabyte
我可以与psql
联系:
]$ psql postgres://a62cf0d1ce2c94b6a8fb7d169da3b75b-2104684727.eu-west-1.elb.amazonaws.com:5433
Pager usage is off.
psql (13.7, server 11.2-YB-2.17.0.0-b0)
Type "help" for help.
yugabyte=# select "_jsonb"->>'_id' as collection, "_jsonb"->>'table' as tablename
from mongodb."_ferretdb_database_metadata";
collection | tablename
------------+----------------
demo | demo_aefd3536
covid | covid_e0d7cdae
(2 rows)
yugabyte=# select count(*) from mongodb.covid_e0d7cdae;
count
-------
237
(1 row)
yugabyte=# select "_jsonb"->>'location' as location
,("_jsonb"->>'new_cases_per_million')::numeric as new_cases_per_million
from mongodb.covid_e0d7cdae
where ("_jsonb"->>'last_updated_date')::date > now()- interval '5 days'
order by 2 desc nulls last limit 10;
location | new_cases_per_million
------------+-----------------------
Brunei | 5449.864
Cyprus | 3742.158
San Marino | 2374.592
Italy | 1423.841
Uruguay | 1096.764
Japan | 1022.971
Tonga | 963.815
Taiwan | 835.377
Mauritius | 783.391
Ireland | 781.986
(10 rows)
获得正确的性能还有很多事情要做。 FerretDB使用一个没有主键的单个JSONB列创建一个表,并在JSON文档的对象ID属性上添加索引。然后,Yugabytedb创建了一个内部ID来在其上分发。最好把它放在碎片钥匙中,但必须从JSON文档中删除。
像Create primary key index for _id automatically #1384
一样,在FerretDB中仍在进行中。如果与ID一起添加了主键,它将成为Yugabytedb中的碎片键。另一个优化将是避免reading information_schema.columns
,该information_schema.columns
在yugabytedb上很慢(所有节点都必须共享目录)。这将在yugabytedb(#7745)上进行优化。如果仍然是一个可伸缩性问题,也有可能为yugabytedb提供后GrestGresQL处理程序。所有这些都是开源ðÖ©yugabytedb和ferretdb是Apache许可证2.0