How did this statement update 3 rows in Postgres?
It seems that random() is executed once per row and not once for all the statement. So each id value is checked against a different random value. You may get 0, 1, 2 or more, even all the rows of the table, although that possibility would be very small even with 10 rows.

If you want it to be executed once and thus get only one value and update only zero or one rows, you could use a CTE, which are known to be evaluated before the main query:

with rnd as
  ( select random() as random )               -- get just one value
select * 
from keyword, rnd 
where id = cast(rnd.random * 99999 as int) ;  -- and use it everywhere


and the same for the UPDATE:

with rnd as
  ( select random() as random ) 
update keyword
set revenue = random()*10                    -- different random value
from rnd 
where id = cast(rnd.random * 99999 as int);