The British national champ-ion kicked for the line early and looked as though he might pay the price as Viviani burst forward from fourth place.
The Cannondale rider drew alongside and even marginally ahead in the final metres, but a second push from Cavendish earned him his second stage victory for Omega Pharma-Quick Step in a time of 3 hours 46.57 seconds after a 155km run from the racecourse at Epsom. Germany's Gerald Ciolek was third.
Team Sky's Sir Bradley Wiggins was safely across the line in the pack and retained his overall lead going into today's final stage to central London, which is expected to end in a sprint finish.
Wiggins, seeking a first victory in his home tour, is 26 seconds ahead of IAM Cycling's Martin Elmiger, the Swiss taking six seconds out of his advantage in yesterday's stage, with Simon Yates third, 66 seconds back, following his victory on Dartmoor on Friday.
Cavendish won on the streets of Guildford last year, but admitted that experience almost hindered rather than helped this time around. "We planned to kick with 700 metres to go, but I am lucky that I have that second kick." he said. "I just mis-timed it a little bit. I was maybe over-confident. I remembered last year kicking out on the cobbles and I thought I'd do the same here.
"I saw Viviani coming and just moved across to put him on the rough part of the road. The guys did a brilliant job and I am so happy. The second kick really took so much out of me so we'll have to see about the last stage."