Your third idea seems to be the closest to what I think of as the industry solution to this sort of problem.
What you're describing is commonly referred to as Ticks. In each tick, a fixed number of actions would be processed for each client in serial. Often times, game servers will have some parallel actions when capable, but this is a much more complicated problem.
A tick is likely going to be in the form of 1/N seconds, N being the number of ticks per second, or Tickrate. This tickrate could be very very often or very infrequent, depending on your use-case. My personal suggestion would be to avoid a tickrate above 60 ticks/second unless you are sure you need more. You probably don't :)
Actions should be atomic. For example, in slither.io, an action such as moving should not immediately process something like breaking your chain, unless the player you hit has already taken their move. This may seem trivial for something on the level of pixels, but if you're dealing with tile-based movement, it becomes much more obvious, and ensures fairness. If Player A moves to tile X,Y and Player B is currently on that tile, you must ensure that by the end of the tick, player B will still be on that tile for any actions to take place between them.
LastlyFurther, I'd say avoid having any of your calculations done on the client side unless they are independently done on the server side. This gets complicated and expensive with physics (many games opt for a lower tick-rate for physics than many other actions and events because of this)
For reference, here is a good link to supplement your own understanding of game servers and multiplayer networking.
Lastly, I'd say don't let fairness ruin your server. If there are exploits that cause your game to be unfair, fix those. If it's a matter of a better computer having slight advantage, I'd say it may not be as big of a deal.