They are two different things.
msg.sender.balance is the protocol-level ethereum balance.
balances[msg.sender would be an element in an array or mapping that contains data, usually a number for internal accounting purposes.
For example if you have an ATM contract that holds ETH for users a mapping like
mapping(address => uint) balances can hold balance information for all of the depositors while the total ETH on hand would be all be in
The users' money outside of the system would be in
msg.sender.balance but that would probably not be relevant. It would not be important check that users don't send more money than they have because the protocol handles that.
It would be crucial to check that the user doesn't withdraw money than the contract's internal accounting says they are entitled to because the contract would have more money available than individual users should receive.
Hope it helps.