Your function needs to be made "idempotent" in order to ensure that a message gets processed only once. In other words, you'll have to maintain state somewhere (maybe a database) that a message was processed successfully, and check that state to make sure a message doesn't get processed twice.
All non-HTTP type Cloud Functions provide a unique event ID in the context parameter provided to the function invocation. If you see a repeat event ID, that means your function is being invoked again for the same message, for whatever reason.
This need for idempotence is not unique to pubsub or cloud scheduler. It's a concern for all non-HTTP type background functions.
A full discussion on writing idempotent functions is a bit too much a Stack Overflow answer, but there is a post in the Google Cloud blog that covers the issue pretty well.
See also: Cloud functions and Firebase Firestore with Idempotency