[Core] Ray Core / Ray Data logging configuration leads to unexpected behavior 
### What happened + What you expected to happen

We use `logging.config.dictConfig(config)` to configure the ray data logger  ([here](https://github.com/ray-project/ray/blob/4f6a419467885c295700f2db6375a298bc575fc2/python/ray/data/_internal/logging.py#L176)), but this is also how ray core configures the ray logger ([here](https://github.com/ray-project/ray/blob/4f6a419467885c295700f2db6375a298bc575fc2/python/ray/_private/ray_logging/logging_config.py#L124)).

For both of these logging configs, we use `disable_existing_loggers: False`. The behavior for this is described as ([logging docs](https://docs.python.org/3/library/logging.config.html#dictionary-schema-details)):
> disable_existing_loggers - whether any existing non-root loggers are to be disabled. This setting mirrors the parameter of the same name in [fileConfig()](https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig). If absent, this parameter defaults to True. This value is ignored if incremental is True.

This description makes it seem like these two logging calls are commutative (regardless of ordering they will produce the same result), but that is not exactly how the python logging module works. If we configure the ray module logger then the ray.data module logger, the results are expected and both are configured. If we instead configure the ray.data module then configure the ray module logger, then the ray.data logging configuration is clobbered. This happens because when configuring the parent logger of a module (e.g. ray module logger is the parent logger of the ray.data module logger), the various handlers associated with the child logger are not guaranteed to be preserved.

Our end goal should be a state where the call order of the logging configurations should not affect the logging behavior.

### Versions / Dependencies

ray==2.39.0

### Reproduction script

```python
import ray
import logging

def report_logger(logger):
    # Collect this logger and its parents
    loggers = []
    current_logger = logger
    while current_logger:
        loggers.append(current_logger)
        if not current_logger.parent or current_logger.parent == current_logger:
            break
        current_logger = current_logger.parent
    
    # Report the configuration of each logger in the hierarchy
    print(f"Logging configuration for '{logger.name}' and its hierarchy:")
    for log in reversed(loggers):  # Start from the root and go down to the given logger
        print(f"\nLogger: {log.name or 'root'} (Level: {logging.getLevelName(log.level)})")
        if log.handlers:
            print("  Handlers:")
            for handler in log.handlers:
                print(f"    - {handler.__class__.__name__} (Level: {logging.getLevelName(handler.level)})")
        else:
            print("  No handlers configured")

print("BEFORE")
report_logger(logging.getLogger("ray.data"))
print()

import ray.data
ray.init(logging_config=ray.LoggingConfig(encoding="JSON", log_level="INFO"))

print("AFTER:")
report_logger(logging.getLogger("ray.data"))
```

### Issue Severity

High: It blocks me from completing my task.