An obvious approach is 2-phase commit or N-phase commit. 2PC and NPC are generally not recommended because it sacrifices performance too much.
* Pros: It is more like a transaction so that you don't have to write rollback logic.
* Cons: It seriously sacrifices system availability since the distributed transaction happens across networks.
A commonly recommended approach is Saga, it's basically compensation.
* Pros: Does not sacrifices system availability since it's an asynchronous/optimal design.
* Cons: Have to write a lot of compensation logic and call them correctly.
* Cons: There are a lot of operations that cannot be compensated. These operations should be arranged in the last steps.
* Cons: What happens if compensation fails?
* Cons: It's eventual consistency, it's not strong atomicity.
I have to admit, I don't try to tackle this problem unless it's really important for the business in a microservices environment.
If your business requires atomicity in most of the places, it's highly recommended to have a carefully designed monolith so you can easily benefit from RDBMS, with your domains modeled in different modules instead of services.