How do I reset a transient when updating a widget’s value?

The simplest thing to do is simply delete the transient when the username is updated. Then the next time get_json() is run it will see that the transient is not set, just as if it had expired, and retrieve the data and save the transient again.

So inside the update() method of your widget class you would do this:

if ( $new_instance['username'] !== $old_instance['username'] ) {
    delete_transient( 'instagram_data' );
}

However one issue with the way you’re setting the transient is that there’s only one transient, instagram_data, and this will be retrieved no matter what username you’re getting data for. So even if you’re deleting the transient when updating the widget, if the user adds multiple widgets with different usernames the transient’s only ever going to contain data for the first username that went through get_json().

You can address this by creating a transient for each user. This would just involve incorporating the username into the transient name by doing this in your get_json() method:

$transient_name = $this->username . '_instagram_data';

if ( false === ( $data = get_transient( $transient_name ) ) )  {
    // etc.
else {
    set_transient( $transient_name, wp_remote_retrieve_body( $request ), 5 );
}

And the code in your widget update method would become:

if ( $new_instance['username'] !== $old_instance['username'] ) {
        delete_transient( $old_instance['username'] . '_instagram_data' );
}

This isn’t required anymore though, because if there’s a new username there’ll be a new transient, but it will help keep the database free of any unnecessary transients.