Browse Source

Fixed #22667 -- Replaced leader/follower terminology with primary/replica

Flavio Curella 11 years ago
parent
commit
beec05686c

+ 4 - 3
docs/ref/settings.txt

@@ -649,10 +649,11 @@ Default: ``None``
 The alias of the database that this database should mirror during
 The alias of the database that this database should mirror during
 testing.
 testing.
 
 
-This setting exists to allow for testing of leader/follower
+This setting exists to allow for testing of primary/replica
+(referred to as master/slave by some databases)
 configurations of multiple databases. See the documentation on
 configurations of multiple databases. See the documentation on
-:ref:`testing leader/follower configurations
+:ref:`testing primary/replica configurations
-<topics-testing-leaderfollower>` for details.
+<topics-testing-primaryreplica>` for details.
 
 
 .. setting:: TEST_NAME
 .. setting:: TEST_NAME
 
 

+ 9 - 9
docs/topics/cache.txt

@@ -222,29 +222,29 @@ won't appear in the models cache, but the model details can be used
 for routing purposes.
 for routing purposes.
 
 
 For example, the following router would direct all cache read
 For example, the following router would direct all cache read
-operations to ``cache_follower``, and all write operations to
+operations to ``cache_replica``, and all write operations to
-``cache_leader``. The cache table will only be synchronized onto
+``cache_primary``. The cache table will only be synchronized onto
-``cache_leader``::
+``cache_primary``::
 
 
     class CacheRouter(object):
     class CacheRouter(object):
         """A router to control all database cache operations"""
         """A router to control all database cache operations"""
 
 
         def db_for_read(self, model, **hints):
         def db_for_read(self, model, **hints):
-            "All cache read operations go to the follower"
+            "All cache read operations go to the replica"
             if model._meta.app_label in ('django_cache',):
             if model._meta.app_label in ('django_cache',):
-                return 'cache_follower'
+                return 'cache_replica'
             return None
             return None
 
 
         def db_for_write(self, model, **hints):
         def db_for_write(self, model, **hints):
-            "All cache write operations go to leader"
+            "All cache write operations go to primary"
             if model._meta.app_label in ('django_cache',):
             if model._meta.app_label in ('django_cache',):
-                return 'cache_leader'
+                return 'cache_primary'
             return None
             return None
 
 
         def allow_migrate(self, db, model):
         def allow_migrate(self, db, model):
-            "Only install the cache model on leader"
+            "Only install the cache model on primary"
             if model._meta.app_label in ('django_cache',):
             if model._meta.app_label in ('django_cache',):
-                return db == 'cache_leader'
+                return db == 'cache_primary'
             return None
             return None
 
 
 If you don't specify routing directions for the database cache model,
 If you don't specify routing directions for the database cache model,

+ 31 - 30
docs/topics/db/multi-db.txt

@@ -197,17 +197,17 @@ Using routers
 
 
 Database routers are installed using the :setting:`DATABASE_ROUTERS`
 Database routers are installed using the :setting:`DATABASE_ROUTERS`
 setting. This setting defines a list of class names, each specifying a
 setting. This setting defines a list of class names, each specifying a
-router that should be used by the leader router
+router that should be used by the master router
 (``django.db.router``).
 (``django.db.router``).
 
 
-The leader router is used by Django's database operations to allocate
+The master router is used by Django's database operations to allocate
 database usage. Whenever a query needs to know which database to use,
 database usage. Whenever a query needs to know which database to use,
-it calls the leader router, providing a model and a hint (if
+it calls the master router, providing a model and a hint (if
 available). Django then tries each router in turn until a database
 available). Django then tries each router in turn until a database
 suggestion can be found. If no suggestion can be found, it tries the
 suggestion can be found. If no suggestion can be found, it tries the
 current ``_state.db`` of the hint instance. If a hint instance wasn't
 current ``_state.db`` of the hint instance. If a hint instance wasn't
 provided, or the instance doesn't currently have database state, the
 provided, or the instance doesn't currently have database state, the
-leader router will allocate the ``default`` database.
+master router will allocate the ``default`` database.
 
 
 An example
 An example
 ----------
 ----------
@@ -225,16 +225,17 @@ An example
     introduce referential integrity problems that Django can't
     introduce referential integrity problems that Django can't
     currently handle.
     currently handle.
 
 
-    The leader/follower configuration described is also flawed -- it
+    The primary/replica (referred to as master/slave by some databases)
+    configuration described is also flawed -- it
     doesn't provide any solution for handling replication lag (i.e.,
     doesn't provide any solution for handling replication lag (i.e.,
     query inconsistencies introduced because of the time taken for a
     query inconsistencies introduced because of the time taken for a
-    write to propagate to the followers). It also doesn't consider the
+    write to propagate to the replicas). It also doesn't consider the
     interaction of transactions with the database utilization strategy.
     interaction of transactions with the database utilization strategy.
 
 
 So - what does this mean in practice? Let's consider another sample
 So - what does this mean in practice? Let's consider another sample
 configuration. This one will have several databases: one for the
 configuration. This one will have several databases: one for the
-``auth`` application, and all other apps using a leader/follower setup
+``auth`` application, and all other apps using a primary/replica setup
-with two read followers. Here are the settings specifying these
+with two read replicas. Here are the settings specifying these
 databases::
 databases::
 
 
     DATABASES = {
     DATABASES = {
@@ -244,20 +245,20 @@ databases::
             'USER': 'mysql_user',
             'USER': 'mysql_user',
             'PASSWORD': 'swordfish',
             'PASSWORD': 'swordfish',
         },
         },
-        'leader': {
+        'primary': {
-            'NAME': 'leader',
+            'NAME': 'primary',
             'ENGINE': 'django.db.backends.mysql',
             'ENGINE': 'django.db.backends.mysql',
             'USER': 'mysql_user',
             'USER': 'mysql_user',
             'PASSWORD': 'spam',
             'PASSWORD': 'spam',
         },
         },
-        'follower1': {
+        'replica1': {
-            'NAME': 'follower1',
+            'NAME': 'replica1',
             'ENGINE': 'django.db.backends.mysql',
             'ENGINE': 'django.db.backends.mysql',
             'USER': 'mysql_user',
             'USER': 'mysql_user',
             'PASSWORD': 'eggs',
             'PASSWORD': 'eggs',
         },
         },
-        'follower2': {
+        'replica2': {
-            'NAME': 'follower2',
+            'NAME': 'replica2',
             'ENGINE': 'django.db.backends.mysql',
             'ENGINE': 'django.db.backends.mysql',
             'USER': 'mysql_user',
             'USER': 'mysql_user',
             'PASSWORD': 'bacon',
             'PASSWORD': 'bacon',
@@ -309,30 +310,30 @@ send queries for the ``auth`` app to ``auth_db``::
             return None
             return None
 
 
 And we also want a router that sends all other apps to the
 And we also want a router that sends all other apps to the
-leader/follower configuration, and randomly chooses a follower to read
+primary/replica configuration, and randomly chooses a replica to read
 from::
 from::
 
 
     import random
     import random
 
 
-    class LeaderFollowerRouter(object):
+    class PrimaryReplicaRouter(object):
         def db_for_read(self, model, **hints):
         def db_for_read(self, model, **hints):
             """
             """
-            Reads go to a randomly-chosen follower.
+            Reads go to a randomly-chosen replica.
             """
             """
-            return random.choice(['follower1', 'follower2'])
+            return random.choice(['replica1', 'replica2'])
 
 
         def db_for_write(self, model, **hints):
         def db_for_write(self, model, **hints):
             """
             """
-            Writes always go to leader.
+            Writes always go to primary.
             """
             """
-            return 'leader'
+            return 'primary'
 
 
         def allow_relation(self, obj1, obj2, **hints):
         def allow_relation(self, obj1, obj2, **hints):
             """
             """
             Relations between objects are allowed if both objects are
             Relations between objects are allowed if both objects are
-            in the leader/follower pool.
+            in the primary/replica pool.
             """
             """
-            db_list = ('leader', 'follower1', 'follower2')
+            db_list = ('primary', 'replica1', 'replica2')
             if obj1._state.db in db_list and obj2._state.db in db_list:
             if obj1._state.db in db_list and obj2._state.db in db_list:
                 return True
                 return True
             return None
             return None
@@ -347,17 +348,17 @@ Finally, in the settings file, we add the following (substituting
 ``path.to.`` with the actual python path to the module(s) where the
 ``path.to.`` with the actual python path to the module(s) where the
 routers are defined)::
 routers are defined)::
 
 
-    DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.LeaderFollowerRouter']
+    DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']
 
 
 The order in which routers are processed is significant. Routers will
 The order in which routers are processed is significant. Routers will
 be queried in the order the are listed in the
 be queried in the order the are listed in the
 :setting:`DATABASE_ROUTERS` setting . In this example, the
 :setting:`DATABASE_ROUTERS` setting . In this example, the
-``AuthRouter`` is processed before the ``LeaderFollowerRouter``, and as a
+``AuthRouter`` is processed before the ``PrimaryReplicaRouter``, and as a
 result, decisions concerning the models in ``auth`` are processed
 result, decisions concerning the models in ``auth`` are processed
 before any other decision is made. If the :setting:`DATABASE_ROUTERS`
 before any other decision is made. If the :setting:`DATABASE_ROUTERS`
 setting listed the two routers in the other order,
 setting listed the two routers in the other order,
-``LeaderFollowerRouter.allow_migrate()`` would be processed first. The
+``PrimaryReplicaRouter.allow_migrate()`` would be processed first. The
-catch-all nature of the LeaderFollowerRouter implementation would mean
+catch-all nature of the PrimaryReplicaRouter implementation would mean
 that all models would be available on all databases.
 that all models would be available on all databases.
 
 
 With this setup installed, lets run some Django code::
 With this setup installed, lets run some Django code::
@@ -369,7 +370,7 @@ With this setup installed, lets run some Django code::
     >>> # This save will also be directed to 'auth_db'
     >>> # This save will also be directed to 'auth_db'
     >>> fred.save()
     >>> fred.save()
 
 
-    >>> # These retrieval will be randomly allocated to a follower database
+    >>> # These retrieval will be randomly allocated to a replica database
     >>> dna = Person.objects.get(name='Douglas Adams')
     >>> dna = Person.objects.get(name='Douglas Adams')
 
 
     >>> # A new object has no database allocation when created
     >>> # A new object has no database allocation when created
@@ -379,10 +380,10 @@ With this setup installed, lets run some Django code::
     >>> # the same database as the author object
     >>> # the same database as the author object
     >>> mh.author = dna
     >>> mh.author = dna
 
 
-    >>> # This save will force the 'mh' instance onto the leader database...
+    >>> # This save will force the 'mh' instance onto the primary database...
     >>> mh.save()
     >>> mh.save()
 
 
-    >>> # ... but if we re-retrieve the object, it will come back on a follower
+    >>> # ... but if we re-retrieve the object, it will come back on a replica
     >>> mh = Book.objects.get(title='Mostly Harmless')
     >>> mh = Book.objects.get(title='Mostly Harmless')
 
 
 
 
@@ -690,7 +691,7 @@ In addition, some objects are automatically created just after
   database).
   database).
 
 
 For common setups with multiple databases, it isn't useful to have these
 For common setups with multiple databases, it isn't useful to have these
-objects in more than one database. Common setups include leader / follower and
+objects in more than one database. Common setups include primary/replica and
 connecting to external databases. Therefore, it's recommended:
 connecting to external databases. Therefore, it's recommended:
 
 
 - either to run :djadmin:`migrate` only for the default database;
 - either to run :djadmin:`migrate` only for the default database;

+ 20 - 19
docs/topics/testing/advanced.txt

@@ -64,16 +64,17 @@ The following is a simple unit test using the request factory::
 Tests and multiple databases
 Tests and multiple databases
 ============================
 ============================
 
 
-.. _topics-testing-leaderfollower:
+.. _topics-testing-primaryreplica:
 
 
-Testing leader/follower configurations
+Testing primary/replica configurations
 -----------------------------------
 -----------------------------------
 
 
-If you're testing a multiple database configuration with leader/follower
+If you're testing a multiple database configuration with primary/replica
-replication, this strategy of creating test databases poses a problem.
+(referred to as master/slave by some databases) replication, this strategy of
+creating test databases poses a problem.
 When the test databases are created, there won't be any replication,
 When the test databases are created, there won't be any replication,
-and as a result, data created on the leader won't be seen on the
+and as a result, data created on the primary won't be seen on the
-follower.
+replica.
 
 
 To compensate for this, Django allows you to define that a database is
 To compensate for this, Django allows you to define that a database is
 a *test mirror*. Consider the following (simplified) example database
 a *test mirror*. Consider the following (simplified) example database
@@ -83,34 +84,34 @@ configuration::
         'default': {
         'default': {
             'ENGINE': 'django.db.backends.mysql',
             'ENGINE': 'django.db.backends.mysql',
             'NAME': 'myproject',
             'NAME': 'myproject',
-            'HOST': 'dbleader',
+            'HOST': 'dbprimary',
              # ... plus some other settings
              # ... plus some other settings
         },
         },
-        'follower': {
+        'replica': {
             'ENGINE': 'django.db.backends.mysql',
             'ENGINE': 'django.db.backends.mysql',
             'NAME': 'myproject',
             'NAME': 'myproject',
-            'HOST': 'dbfollower',
+            'HOST': 'dbreplica',
             'TEST_MIRROR': 'default'
             'TEST_MIRROR': 'default'
             # ... plus some other settings
             # ... plus some other settings
         }
         }
     }
     }
 
 
-In this setup, we have two database servers: ``dbleader``, described
+In this setup, we have two database servers: ``dbprimary``, described
-by the database alias ``default``, and ``dbfollower`` described by the
+by the database alias ``default``, and ``dbreplica`` described by the
-alias ``follower``. As you might expect, ``dbfollower`` has been configured
+alias ``replica``. As you might expect, ``dbreplica`` has been configured
-by the database administrator as a read follower of ``dbleader``, so in
+by the database administrator as a read replica of ``dbprimary``, so in
-normal activity, any write to ``default`` will appear on ``follower``.
+normal activity, any write to ``default`` will appear on ``replica``.
 
 
 If Django created two independent test databases, this would break any
 If Django created two independent test databases, this would break any
-tests that expected replication to occur. However, the ``follower``
+tests that expected replication to occur. However, the ``replica``
 database has been configured as a test mirror (using the
 database has been configured as a test mirror (using the
 :setting:`TEST_MIRROR` setting), indicating that under testing,
 :setting:`TEST_MIRROR` setting), indicating that under testing,
-``follower`` should be treated as a mirror of ``default``.
+``replica`` should be treated as a mirror of ``default``.
 
 
-When the test environment is configured, a test version of ``follower``
+When the test environment is configured, a test version of ``replica``
-will *not* be created. Instead the connection to ``follower``
+will *not* be created. Instead the connection to ``replica``
 will be redirected to point at ``default``. As a result, writes to
 will be redirected to point at ``default``. As a result, writes to
-``default`` will appear on ``follower`` -- but because they are actually
+``default`` will appear on ``replica`` -- but because they are actually
 the same database, not because there is data replication between the
 the same database, not because there is data replication between the
 two databases.
 two databases.
 
 

+ 1 - 1
tests/migrations/test_operations.py

@@ -980,7 +980,7 @@ class MultiDBOperationTests(MigrationTestBase):
     multi_db = True
     multi_db = True
 
 
     def setUp(self):
     def setUp(self):
-        # Make the 'other' database appear to be a follower of the 'default'
+        # Make the 'other' database appear to be a replica of the 'default'
         self.old_routers = router.routers
         self.old_routers = router.routers
         router.routers = [MigrateNothingRouter()]
         router.routers = [MigrateNothingRouter()]
 
 

+ 1 - 1
tests/multiple_database/routers.py

@@ -4,7 +4,7 @@ from django.db import DEFAULT_DB_ALIAS
 
 
 
 
 class TestRouter(object):
 class TestRouter(object):
-    # A test router. The behavior is vaguely leader/follower, but the
+    # A test router. The behavior is vaguely primary/replica, but the
     # databases aren't assumed to propagate changes.
     # databases aren't assumed to propagate changes.
     def db_for_read(self, model, instance=None, **hints):
     def db_for_read(self, model, instance=None, **hints):
         if instance:
         if instance:

+ 19 - 19
tests/multiple_database/tests.py

@@ -854,7 +854,7 @@ class QueryTestCase(TestCase):
         self.assertEqual(book.editor._state.db, 'other')
         self.assertEqual(book.editor._state.db, 'other')
 
 
     def test_subquery(self):
     def test_subquery(self):
-        """Make sure as_sql works with subqueries and leader/follower."""
+        """Make sure as_sql works with subqueries and primary/replica."""
         sub = Person.objects.using('other').filter(name='fff')
         sub = Person.objects.using('other').filter(name='fff')
         qs = Book.objects.filter(editor__in=sub)
         qs = Book.objects.filter(editor__in=sub)
 
 
@@ -919,7 +919,7 @@ class RouterTestCase(TestCase):
     multi_db = True
     multi_db = True
 
 
     def setUp(self):
     def setUp(self):
-        # Make the 'other' database appear to be a follower of the 'default'
+        # Make the 'other' database appear to be a replica of the 'default'
         self.old_routers = router.routers
         self.old_routers = router.routers
         router.routers = [TestRouter()]
         router.routers = [TestRouter()]
 
 
@@ -1071,7 +1071,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             dive.editor = marty
             dive.editor = marty
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments of original objects haven't changed...
         # Database assignments of original objects haven't changed...
         self.assertEqual(marty._state.db, 'default')
         self.assertEqual(marty._state.db, 'default')
@@ -1089,7 +1089,7 @@ class RouterTestCase(TestCase):
         except Book.DoesNotExist:
         except Book.DoesNotExist:
             self.fail('Source database should have a copy of saved object')
             self.fail('Source database should have a copy of saved object')
 
 
-        # This isn't a real leader-follower database, so restore the original from other
+        # This isn't a real primary/replica database, so restore the original from other
         dive = Book.objects.using('other').get(title='Dive into Python')
         dive = Book.objects.using('other').get(title='Dive into Python')
         self.assertEqual(dive._state.db, 'other')
         self.assertEqual(dive._state.db, 'other')
 
 
@@ -1097,7 +1097,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             marty.edited = [pro, dive]
             marty.edited = [pro, dive]
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Assignment implies a save, so database assignments of original objects have changed...
         # Assignment implies a save, so database assignments of original objects have changed...
         self.assertEqual(marty._state.db, 'default')
         self.assertEqual(marty._state.db, 'default')
@@ -1111,7 +1111,7 @@ class RouterTestCase(TestCase):
         except Book.DoesNotExist:
         except Book.DoesNotExist:
             self.fail('Source database should have a copy of saved object')
             self.fail('Source database should have a copy of saved object')
 
 
-        # This isn't a real leader-follower database, so restore the original from other
+        # This isn't a real primary/replica database, so restore the original from other
         dive = Book.objects.using('other').get(title='Dive into Python')
         dive = Book.objects.using('other').get(title='Dive into Python')
         self.assertEqual(dive._state.db, 'other')
         self.assertEqual(dive._state.db, 'other')
 
 
@@ -1119,7 +1119,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             marty.edited.add(dive)
             marty.edited.add(dive)
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Add implies a save, so database assignments of original objects have changed...
         # Add implies a save, so database assignments of original objects have changed...
         self.assertEqual(marty._state.db, 'default')
         self.assertEqual(marty._state.db, 'default')
@@ -1133,7 +1133,7 @@ class RouterTestCase(TestCase):
         except Book.DoesNotExist:
         except Book.DoesNotExist:
             self.fail('Source database should have a copy of saved object')
             self.fail('Source database should have a copy of saved object')
 
 
-        # This isn't a real leader-follower database, so restore the original from other
+        # This isn't a real primary/replica database, so restore the original from other
         dive = Book.objects.using('other').get(title='Dive into Python')
         dive = Book.objects.using('other').get(title='Dive into Python')
 
 
         # If you assign a FK object when the base object hasn't
         # If you assign a FK object when the base object hasn't
@@ -1196,7 +1196,7 @@ class RouterTestCase(TestCase):
         mark = Person.objects.using('default').create(pk=2, name="Mark Pilgrim")
         mark = Person.objects.using('default').create(pk=2, name="Mark Pilgrim")
 
 
         # Now save back onto the usual database.
         # Now save back onto the usual database.
-        # This simulates leader/follower - the objects exist on both database,
+        # This simulates primary/replica - the objects exist on both database,
         # but the _state.db is as it is for all other tests.
         # but the _state.db is as it is for all other tests.
         pro.save(using='default')
         pro.save(using='default')
         marty.save(using='default')
         marty.save(using='default')
@@ -1213,7 +1213,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             marty.book_set = [pro, dive]
             marty.book_set = [pro, dive]
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments don't change
         # Database assignments don't change
         self.assertEqual(marty._state.db, 'default')
         self.assertEqual(marty._state.db, 'default')
@@ -1232,7 +1232,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             marty.book_set.add(dive)
             marty.book_set.add(dive)
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments don't change
         # Database assignments don't change
         self.assertEqual(marty._state.db, 'default')
         self.assertEqual(marty._state.db, 'default')
@@ -1251,7 +1251,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             dive.authors = [mark, marty]
             dive.authors = [mark, marty]
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments don't change
         # Database assignments don't change
         self.assertEqual(marty._state.db, 'default')
         self.assertEqual(marty._state.db, 'default')
@@ -1273,7 +1273,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             dive.authors.add(marty)
             dive.authors.add(marty)
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments don't change
         # Database assignments don't change
         self.assertEqual(marty._state.db, 'default')
         self.assertEqual(marty._state.db, 'default')
@@ -1311,7 +1311,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             bob.userprofile = alice_profile
             bob.userprofile = alice_profile
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments of original objects haven't changed...
         # Database assignments of original objects haven't changed...
         self.assertEqual(alice._state.db, 'default')
         self.assertEqual(alice._state.db, 'default')
@@ -1342,7 +1342,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             review1.content_object = dive
             review1.content_object = dive
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments of original objects haven't changed...
         # Database assignments of original objects haven't changed...
         self.assertEqual(pro._state.db, 'default')
         self.assertEqual(pro._state.db, 'default')
@@ -1361,7 +1361,7 @@ class RouterTestCase(TestCase):
         except Book.DoesNotExist:
         except Book.DoesNotExist:
             self.fail('Source database should have a copy of saved object')
             self.fail('Source database should have a copy of saved object')
 
 
-        # This isn't a real leader-follower database, so restore the original from other
+        # This isn't a real primary/replica database, so restore the original from other
         dive = Book.objects.using('other').get(title='Dive into Python')
         dive = Book.objects.using('other').get(title='Dive into Python')
         self.assertEqual(dive._state.db, 'other')
         self.assertEqual(dive._state.db, 'other')
 
 
@@ -1369,7 +1369,7 @@ class RouterTestCase(TestCase):
         try:
         try:
             dive.reviews.add(review1)
             dive.reviews.add(review1)
         except ValueError:
         except ValueError:
-            self.fail("Assignment across leader/follower databases with a common source should be ok")
+            self.fail("Assignment across primary/replica databases with a common source should be ok")
 
 
         # Database assignments of original objects haven't changed...
         # Database assignments of original objects haven't changed...
         self.assertEqual(pro._state.db, 'default')
         self.assertEqual(pro._state.db, 'default')
@@ -1444,7 +1444,7 @@ class RouterTestCase(TestCase):
         self.assertEqual(pro.reviews.db_manager('default').all().db, 'default')
         self.assertEqual(pro.reviews.db_manager('default').all().db, 'default')
 
 
     def test_subquery(self):
     def test_subquery(self):
-        """Make sure as_sql works with subqueries and leader/follower."""
+        """Make sure as_sql works with subqueries and primary/replica."""
         # Create a book and author on the other database
         # Create a book and author on the other database
 
 
         mark = Person.objects.using('other').create(name="Mark Pilgrim")
         mark = Person.objects.using('other').create(name="Mark Pilgrim")
@@ -1482,7 +1482,7 @@ class AuthTestCase(TestCase):
     multi_db = True
     multi_db = True
 
 
     def setUp(self):
     def setUp(self):
-        # Make the 'other' database appear to be a follower of the 'default'
+        # Make the 'other' database appear to be a replica of the 'default'
         self.old_routers = router.routers
         self.old_routers = router.routers
         router.routers = [AuthRouter()]
         router.routers = [AuthRouter()]