作为一名开发者,我一直尝试通过试验和构建来学习新技术。我最近对无服务器数据库颇感兴趣,该技术有望加快部署、增强可扩展性及改善开发者体验。我在测试多个产品后,决定将个人网站由使用Firebase和Redis改用PlanetScale,这是建立在MySQL和Vitess上的新的无服务器数据库平台,是为YouTube 提供支持而开发的开源平台。
我选择PlanetScale的原因如下:
- 数据库分支:我可以使用心智模型与Git相同的数据库。每次更改我的数据库模式,我都打开部署请求。然后,我可以将这些更改合并回到主数据库分支中。
- Prisma支持:与Prisma结合使用,可以很轻松地处理数据库迁移。
- 无连接:由于PlanetScale是无服务器,因此可以承受数千个同时连接。几乎可以把这认为是无连接,因为我不需要担心池化或其他常见的反对意见。
- 10秒内部署:我在测试13个数据库后,发现PlanetScale部署速度最快。使用它几周并监控性能后,我看到API平均在大约150ms内解析(见下面的结果)。
Firebase和Redis
我的网站以前使用Google Firebase和Redis用于实时博文阅读量和留言簿。决定选择这些技术主要是想学习一下。Firebase和Redis(借助Upstash)都很易于上手,无需思考即可扩展,在无服务器环境下运行顺畅。但是我想转而使用基于SQL的数据库(MySQL或PostgreSQL),以获得新的学习体验。
重建SQL
我发现自己在SQL有内置功能的地方编写JavaScript。比如说,我使用Firebase获取 JSON对象阅读量,然后将这些值相加以找到总的阅读量。
constsnapshot=awaitdb.ref('views').once('value'); constviews=snapshot.val(); constallViews=Object.values(views).reduce((total,value)=>total+value); WithSQL,youcanuseSUM()instead. SELECTSUM(count)astotal FROMviews;
排序同样如此。以前我使用JavaScript sort,现在使用ORDER BY。虽然Firebase确实有类似功能,但我并不使用它。
SELECT*FROMguestbook ORDERBYupdated_atDESC;
SQL是成熟的技术。它已存在多年,会继续存在多年。我在以前的工作中用过它,但仍觉得可以更深入地理解它。我也喜欢使用PostgreSQL(推荐Supabase),强烈推荐考虑该解决方案。
我还坚信使用自己推荐的工具。如果我没有实际动手编写代码、在生产环境中运行应用程序,就很难有把握地向别人推荐产品。我使用PlanetScale Vercel Integration后,大为惊喜。只需点击几下鼠标,我就可以部署整个全栈应用程序。正如开头提到的,数据库迁移与我的心智模型相一致。
迁移现有数据
可能有更好的方法来迁移,但我将数据迁移到PlanetScale的自创解决方案如下:
- 从我的Firebase实时数据库导出JSON数据
- 使用HVALS和TablePlus,从我的Redis集群导出JSON数据
- 在PlanetScale中创建新的数据库分支,用于添加表的模式迁移
- 创建两个新的API路由,负责加载JSON数据和INSERT INTO(插入到)MySQL
- 在数据库分支上验证API正确处理和迁移数据
- 创建拥有新模式更改的部署请求,并将其合并到main中
- 最后,点击API,将JSON数据迁移到main
- 完毕!
下面是我使用的两个脚本,供参考。
importdbfrom'lib/planetscale'; importguestbookDatafrom'data/guestbook'; exportdefaultasyncfunctionhandler(req,res){ consttoISOString=(unixTimestampInMs)=> newDate(unixTimestampInMs).toJSON().slice(0,19).replace('T',''); letquery=`INSERTINTOguestbook(email,updated_at,body,created_by) VALUES`; constescapeStr=(str)=> str .replace(/\\/g,'\\\\') .replace(/\$/g,'\\$') .replace(/'/g,"\\'") .replace(/"/g,'\\"'); guestbookData.forEach((item,key)=>{ varvalue=JSON.parse(item['value']); query+=`("${ value.email?`${value.email}`:'not@provided.com' }","${toISOString(value.updated_at)}","${escapeStr(value.body)}","${ value.created_by }")`; if(key===guestbookData.length-1){ query+=';'; }else{ query+=','; } }); const[rows]=awaitdb.query(query); returnres.status(201).json(rows[0]); } importdbfrom'lib/planetscale'; importviewsDatafrom'data/views'; exportdefaultasyncfunctionhandler(req,res){ letquery=`INSERTINTOviews(slug,count) VALUES`; constslugs=Object.keys(viewsData['views']); slugs.forEach((slug,key)=>{ constcount=viewsData['views'][slug]; query+=`("${slug}",${count})`; if(key===slugs.length-1){ query+=';'; }else{ query+=','; } }); const[rows]=awaitdb.query(query); returnres.status(201).json(rows[0]); }
以下是我的PlanetScale模式,用于跟踪博文阅读量和留言簿留言。
CREATETABLE`views`( `slug`varchar(128)NOTNULL, `count`bigintNOTNULLDEFAULT'1', PRIMARYKEY(`slug`) ) CREATETABLE`guestbook`( `id`bigintNOTNULLAUTO_INCREMENT, `email`varchar(256)NOTNULL, `body`varchar(500)NOTNULL, `created_by`varchar(256)NOTNULL, `created_at`datetime(6)NOTNULLDEFAULTCURRENT_TIMESTAMP(6), `updated_at`datetime(6)NOTNULLDEFAULTCURRENT_TIMESTAMP(6), PRIMARYKEY(`id`) )
结果
我一直使用Checkly来监控连接到PlanetScale的生产级API的性能。Checkly让我可以设置警报,那样出现停运或性能降到接受的阈值以下时发出警报。迄今为止,我发现我的Next.js API Routes在us-east的Vercel上部署为无服务器函数时延迟约150ms。
PlanetScale性能小结
如下图所示,与我之前的Firebase实现相比,响应时间显著加快(请注意我何时进行切换)。 此外,拥有一项而不是两项服务可以清理代码,需要较少的环境变量即可连接到每项服务。
转载请注明:IT运维空间 » 运维技术 » 如何迁移到PlanetScale的无服务器数据库?
发表评论