Background
Recently encountered a problem in mobile development app: between the server and the client needs to be modified, deleted, updated, add and other operations synchronization, for this study, which leanote reference the Evernote app synchronization principle.
Leanote synchronization Mechanism reference Evernote mechanism, synchronization mechanism for Evernote reference: Http://dev.evernote.com/media/pdf/edam-sync.pdf
Objective
Leanote is mainly composed of notebook, Note, Tag, File (image/Attachment). File attached to note exists. When the note is deleted, the file it contains is also deleted.
Each account (User), Notebook, Note, tag contains the field USN (Update Sequence number), which is the most important field in the entire synchronization system. The USN of user is used to identify each modification in the account, and each time the notebook is modified, the user's USN will be +1 after the tag. While notebook, Note, the USN of the tag identifies an account USN when the object was last modified.
For example, at some point the user's USN is 100. When I add a note Note1, the USN of the user becomes 101, and the Note1 USN is also 101. Then I add a note Note2, when the user's USN will become 102,note2 's USN is also 102,note1 or 101. In this way we record after each synchronization of the user's USN is saved as LASTUSN, the next time if the account of the USN > Lastusn, the account of something has been modified, you need to first synchronize the server side of the changes to local.
When the account is logged in for the first time, a full-volume synchronization is required at this point, synchronizing all and data on the server to local. After the user has been locally manipulated, the modified data needs to be synchronized each time.
The basic steps of synchronization are as follows:
- Pull: Determine if there is any new data on the server, that is, by comparing local LASTSYNCUSN with the servers-side USN, if the local LASTSYNCUSN < server-side USN indicates that the server has been modified, the data on the servers needs to be synchronized locally. See "Synchronizing Data" for details.
- Push: Sends locally modified data to the server side. See "Sending changes" for details.
- Save status: Gets the latest synchronization status, saving the latest USN on the server side as local LASTSYNCUSN.
Synchronizing Data Pull
Synchronize data from the server side to local.
First determine whether the server has new data, that is, by local LASTSYNCUSN and server-side USN comparison, if the local LOASTSYNCUSN < server-side USN, indicating that the service side has been modified, it is necessary to synchronize the data on the servers to local.
To synchronize data steps:
- Sync Notebook
- Sync Note
- Sync tag
Synchronization notebook, Note, tag steps are basically the same, now take the synchronous notebook as an example, pseudo-code:
Gets the data to be synchronized remotely var lastsyncusn = Getlastsyncusn (); The locally saved usnfunction Syncnotebook (LASTSYNCUSN) {var afterusn = Lastsyncusn;//Represents the Lastsyncusn while after taking notebook ( true) {//Call API, Fetch AFTERUSN of 10 notebooks var notebooks = Api.call ('/api/notebook/getsyncnotebooks?afterusn=afterus N&maxentry=10 '); Save the acquired notebooks to the local updatenotebooktolocal (notebooks); If the notebook = = 10 is taken, it is likely that there is a notebook if (notebooks.length = =) {Afterusn = Notebooks[notebooks) to synchronize. LENGTH-1]. USN; Take the largest USN as the next standard}//If < is not enough, there is no notebook to synchronize. else {break; }}//save remote Data to local function updatenotebooktolocal (notebooks) {for (var i = 0; i < notebooks.length; ++i) {V AR notebook = notebooks[i]; Gets the local notebook var Localnotebook = Getlocalnotebook (notebook. Notebookid); The server side has been deleted, and the local if (notebook) is removed at this time. IsDeleted) {Deletelocalnotebook (notebook. Notebookid); } else {//If there is no local modification, save notebook to local if (!localnotebook.isdirty) {Db.updatetolo Cal (notebook. Notebookid, notebook); }//local update, need to handle conflict at this time else {}}}}
Get note, tag to synchronize the data API for
- /api/note/getsyncnotes
- /api/tag/getsynctags
How do I handle conflicts?
The cause of the conflict occurred: it was locally modified, and the server was modified. At this point, the data on the server is synchronized to local, sending the isdirty=true of the local data. Conflicts need to be handled at this time.
Handling conflicts is done by the client, and the most extreme is that the client can completely overwrite the data on the server to the local, or discard the server-side data completely and use locally modified data.
However, this is likely to result in loss of data, so when a conflict is encountered, the data on the server should be downloaded to the local and local conflicting data to be correlated, and the last data to be used is determined by the user.
Send Change Push
Sends locally modified data to the server side.
To send a change step:
- Send the Modified Notebook
- Send the modified note
- Send the modified tag
Send the change, that is, get the locally modified notebook, Note, Tag, and then send the modified information to the server side. So the local need to have an identity to identify which data has changed. For example, you can set a isdirty field to identify. If the local note has been modified, update the note isdirty to true, and set its isdirty=false if the change is successful.
Below by sending notebook changes as an example:
function Sendnotebookchanges () { var dirtynotebooks = Getdirtynotebooks (); for (var i = 0; i < dirtnotebooks.length; ++i) { var dirtynotebook = dirtynotebooks[i]; Call API, send change, must be sent to USN, server side based on the past USN to determine whether the conflict var ret = api.call ('/api/notebook/updatenotebook?usn= Dirtynotebook.usn&title=dirtynotebook.title '); The modification succeeds, the USN returned by the server is updated locally, and IsDirty is set to False if (ret. Ok) { Updatelocalnotebook (notebook.id, {usn:ret). USN, Isdirty:false}); } The update failed with a conflict, indicating that the data on the server is new locally, and that conflicts need to be resolved, //conflict resolution methods can overwrite the server's data to the local else if (ret. MSG = = "conflict") { var servernote = apil.call ('/api/notebook/getnotebook?notebookid=dirtynotebook.id '); Updatenotebooktolocal (Servernote);}}}
To modify the note, the tag API is:
- /api/note/updatenote, Deletenote
- /api/tag/addtag, Deletetag
Get the latest sync status
Call API "/api/user/getsyncstate" to get the latest synchronization status, save the USN to local for LASTSYNCUSN;
weekly updates follow :http://weibo.com/hanjunqiang Sina Weibo! mobile phone plus
iOS Developer Chat QQ Group: 446310206
The leanote synchronization mechanism of the note-like app Han Junqiang Blog