Rob*_*bin 5 postgresql sqlite offline
我想制作一个离线优先的待办事项应用程序,它可以在移动应用程序(SQLite)和网络应用程序(PostgreSQL)上运行。该应用程序将具有以下商业模式:
用户:
去做:
创建新用户:
创建新的待办事项:
id如果帖子成功,请在移动应用程序中创建具有相同成功待办事项的待办事项。如果手机处于离线状态并且我没有任何 ID,我不确定如何创建新的待办事项。如果我为移动应用程序创建一个虚拟 ID,它可能会与其他待办事项 ID 发生冲突。或者我应该在移动应用程序中使用 UUID 作为我所有待办事项的 ID,然后将其发布到网络应用程序?其他离线优先应用程序数据库设计如何工作?
如果手机处于离线状态并且我没有任何 ID,我不确定如何创建新的待办事项。如果我为移动应用程序创建一个虚拟 ID,它可能会与其他待办事项 ID 发生冲突。
这些是用于键入数据的潜在解决方案:
使用 UUID / GUID:优点是它很简单并且可以最大限度地减少碰撞的可能性(尽管并不能完全消除它)。缺点是它们对人类不友好,并且会稍微影响查询性能。
使用Snowflake ID:优点是它还提供了高水平的唯一性,有助于最大限度地减少冲突,更具人类可读性,并且在索引时比 GUID 的键性能更高(因为它们更易于排序)。Twitter 和 Instagram 等大公司也使用它,因此它有一些支持。缺点是它仍然比整数或自然键对人类不太友好。
雪花是 64 位二进制的。(只有 63 位用于容纳有符号整数。)前 41 位是时间戳,表示自所选纪元以来的毫秒数。接下来的 10 位代表机器 ID,防止冲突。另外十二位代表每台机器的序列号,以允许在同一毫秒内创建多个雪花。最终的数字一般以十进制序列化。
使用复合主键,可以自然地将数据与冲突(例如用户的冲突)解耦。在您的情况下,您的Todos表的主键可以在 上定义(id, user_id)。Users那么,如果两个在离线时生成相同的值也没关系id,因为您的密钥也已定义并解耦user_id。
使用标识列的组合:一个是LocalIdentityKeySQLiteAUTOGENERATED数据库中实体中的关键列(以及 PostgreSQL 中基于可空占位符整数的字段),另一个是PostgreSQL 中GlobalIdentityKey定义为关键列GENERATED ALWAYS AS IDENTITY实体,并且是 SQLite 实体中基于整数的可空占位符列。
#4 的工作流程将遵循以下步骤:
在移动应用程序上创建实体的新实例,并将其本地保存到 SQLite 数据库。它LocalIdentityKey是自动生成的。
该应用程序将该实体同步到远程 PostgreSQL 数据库。如果应用程序在线,则这种情况会立即发生,或者会延迟到应用程序下次重新在线时发生。INSERT将新实体添加到 PostgreSQL 数据库后,INSERT应使用RETURNING子句调用 ,如StackOverflow 答案中的选项 3中所述。这将允许您获取GlobalIdentityKeyPostgreSQL 实体中新自动生成的标识值。
将本地 SQLite 实体实例的占位符字段更新为GlobalIdentityKey从 PostgreSQL 返回的值。
这种方法的优点是您使用更标准的基于整数的密钥,从索引的角度来看,它更具有人类可读性和性能,并且保证不会发生冲突。缺点是需要更多的工作来连接。
另外,如果您采用上述解决方案 1 或 2(发生冲突的可能性很小),那么尝试/捕获INSERT通过重新生成新密钥来处理冲突非常重要。除了INSERT将该实体远程连接到 PostgreSQL 数据库时,还需要在实体的本地副本上更新此新密钥。您可能需要重试多次(直到选择唯一值),因为多次连续冲突是可能的(尽管很少见)。
| 归档时间: |
|
| 查看次数: |
957 次 |
| 最近记录: |