I am winging it here. Make a flexible / progressively enhanced shopping cart.
Not Logged In
Plan A) If Web Storage, use it (session storage / local storage) knowing that ALL customers' cart data can be aggregated into a tracking cart database table (with time stamps and session ids) using AJAX, too. Synchronization and pruning is key (client, tracking table). No server-side session storage of individual cart data is required.
If the browser closes, the cart can be re-established. Closing the browser gracefully should result in an AJAX call that prunes the tracking table.
The tracking cart is not authoritative (used to impact / reserve inventory) because it does not represent an identified customer on the verge of paying. Only if the customer hits check-out will the items in the tracking cart matter in terms of inventory (there is still more to do, though).
Plan B) Else, fall back to logic for [server-side] session cookies only. Use AJAX to read/write data in the centralized cart tracking table. The client never stores individual cart data, nor is it stored in session data (database driven, or not). As long as the client is not logged in, their cart data is in the centralized tracking cart only.
If the browser closes, the client-side cart is lost for good. If the browser closes gracefully, items will also be deleted from the tracking table utilizing an AJAX call. Otherwise, old cart data in the database is pruned by activity time stamps.
Alternative Plan B) Implement a persistent client-side solution using standard, encrypted cookies. This way, whether the browser closes gracefully or not, the client-side cart can be re-established and the tracking cart table updated. This would support older user agents and save them some frustration at the cost of doing more programming and testing.
Note: You must anticipate and handle the reality that session ids will change throughout the lifetime of the session. If you want to avoid session fixation, you cannot use the same session id over and over again for each HTTP request. Hence, you must UPDATE the session id in the master tracking table upon each request.* This could be a lot of updates if many users are not logged in and they have many products in their carts.
Logged In
When a customer logs in, you copy their tracking cart contents to their own shopping cart table (regular table, not in session). The shell game will now be played between the client, cart table data, and the master tracking cart. The user's cart contents are now persistent regardless of the user-agent.
The user's shopping cart table is not yet authoritative, either.
Only when the users hits check out will the user's cart contents impact inventory availability. Only after purchase will actual inventory decrease.
That last line brings up an important point. There is a difference between what is available and what is in stock. Due to a website's concurrency of use, any number of people may put the same item in their cart without it becoming unavailable.
If there are 10 Linux books in stock, 20 people could put 1 copy into their cart. The first ten are not a problem, but should the second ten be shown a message SOLD OUT? No. What if 15 people walk away, say never-mind, but never empty their cart? All should see IN STOCK, but only those who hit check-out should impact availability. Those who pay should affect inventory.
Thus, in setting up your product tables, be sure to have two fields for tracking products: availability and quantity. They are related, but in the e-commerce sense they are not the same.
Final Note: In a load balanced web server scenario (Amazon Web Service users will probably agree), it is more likely that sessions will be handled by a database because it makes it easier to centralize the data. While it is possible to have a networked, centralized, and file based / NFS session store on a NAS type solution, that may not be advisable or optimal (latency, file locking issues).