WP_Query & Duplicate entries

There shouldn’t be a foreach loop inside the while. The while loops over posts, so you don’t need another foreach. The while loop in this context is what WordPress calls “The Loop”.

See the section of documentation for The Loop on secondary queries here.

So your loop should look like this:

<?php while ( $posts->have_posts() ) : $posts->the_post(); ?>
    <?php the_title(); ?><br>
<?php endwhile; ?>