请教一个问题,就是redis备份的话,是把所有从redis服务器启动开始,把所有的数据都做备份,还是只备份近期的数据?还有就是mysql和redis之间,哪些需要备份到mysql里,查询redis没有,从mysql里拿并写入redis?
Redis备份的策略,可以根据需求来决定备份全量数据还是只备份近期数据。
根据业务需求和数据特征,可以选择性地将数据从MySQL备份到Redis,或从MySQL中读取并更新到Redis中,以满足数据持久化和缓存的需求,并确保数据的完整性和可用性。
1.强一致(向数据库插入一条数据时,同时向redis中也插入一条数据)
2.定时任务:设置过期时间
结合实际场景,解决redis和mysql的数据一致性
在并发不高的情况下:读操作优先读取redis,不存在的话就去访问MySQL数据库,并把从数据库中读到的数据写回Redis中;写操作的话,直接写MySQL,成功后再写入Redis(可以在MySQL数据库业务代码中定义CRUD触发器,在触发CRUD操作后写数据到Redis,也可以在Redis端解析mysql的binlog,再做相应的操作)。
在并发高的情况下:读操作和上面一样,写操作是异步写,写入Redis后直接返回,然后定时定期写入MySQL。或者用MQ异步将mysql数据同步到redis。
场景一:
问题:当更新数据时,如更新某商品的库存,当前商品的数据库存是100、缓存存的是100,现在都要更新为99,先更新数据库更改成99,然后删除缓存,如果删除缓存失败了,这意味着数据库存的是99,而缓存还是100,这就导致数据库和缓存的数据不一致。(加一个1/0在mysql和redis之间)
解决方法:
这种情况应该是先删除缓存,然后在更新数据库。如果删除缓存失败,那就不要更新数据库。如果说删除缓存成功,而更新数据库失败了,那查询的时候只是从数据库里查了旧的数据而已,这样就能保持数据库与缓存的一致性。
场景二:
问题:在高并发的情况下,如果当删除完缓存的时候,这时去更新数据库,但还没有更新完,另外一个请求来查询数据,发现缓存里没有,就去数据库里查,还是以上面商品库存为例,如果数据库中产品的库存是100,那么查询到的库存是100,然后插入缓存,插入完缓存后,原来那个更新数据库的线程把数据库更新为了99,导致数据库与缓存数据不一致的情况。(缓存中是脏数据)
解决方法:
遇到这种情况,可以用第三方MQ队列去解决这个问题,创建几个队列,如20个,根据商品的ID去做hash值,然后对队列个数取摸,当有数据更新请求时,先把它丢到队列里去,当更新完后在从队列里去除,如果在更新的过程中,遇到以上场景,先去缓存里看下有没有数据,如果没有,可以先去队列里看是否有相同商品ID在做更新,如果有也把查询的请求发送到队列里去,然后同步等待缓存更新完成。
这里有一个优化点,如果发现队列里有一个查询请求了,那么就不要放新的查询操作进去了,用一个while(true)循环去查询缓存,循环个200MS左右,如果缓存里还没有则直接取数据库的旧数据,一般情况下是可以取到的。
问题1:在进行redis备份时,是需要备份从redis服务器启动开始到现在的所有数据,还是只备份近期的数据?
回答1:在进行redis备份时,可以选择备份从redis服务器启动开始到现在的所有数据,也可以选择只备份近期的数据。这取决于您对备份策略的需求和存储资源的限制。
如果您选择备份从redis服务器启动开始到现在的所有数据,您可以使用Redis的持久化功能,通过将数据写入到磁盘上的RDB文件或AOF文件来实现。RDB文件是一个紧凑的二进制文件,它可以定期创建快照并保存redis服务器在某个时间点的所有数据。AOF文件是一个追加写日志文件,它将每个写操作追加到文件中,以便在服务器重启时可以重新构建数据。
如果您只想备份近期的数据,您可以使用Redis的复制功能来实现。复制将整个redis数据库的所有数据从主服务器复制到一个或多个从服务器。在进行备份之前,您可以通过执行命令BGSAVE
来触发主服务器的RDB持久化操作,这样从服务器将会将主服务器的数据进行复制。复制期间,从服务器将持续地接收并复制主服务器的数据更新。
问题2:在mysql和redis之间,有哪些数据需要备份到mysql中,而不需要在redis中查询,需要从mysql中获取并写入redis中呢?
回答2:在mysql和redis之间,通常需要备份到mysql中的数据是那些不适合或无法存储在redis中的数据。这些数据可能需要进行持久化存储、事务管理或复杂查询等操作。
一些常见的需要备份到mysql中的数据可以包括用户信息、订单信息、配置信息、日志信息等。这些数据通常需要在redis中查询的话会增加复杂性或性能开销,并且可能需要进行持久化存储或更严格的事务管理。
具体的备份流程可以根据应用的需求和复杂性进行设计。一种常见的做法是,在数据更新时,先将数据写入mysql中,然后再更新到redis中。这可以通过使用分布式事务或消息队列等技术来实现数据的一致性。
以下是一个示例代码,演示了如何在数据更新时备份到mysql中并同步到redis中:
import redis
import mysql.connector
# 连接到redis服务器
redis_client = redis.Redis(host='localhost', port=6379)
# 连接到mysql服务器
mysql_connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="yourdatabase"
)
# 执行数据更新操作
def update_data(key, value):
# 更新mysql中的数据
mysql_cursor = mysql_connection.cursor()
sql = "UPDATE yourtable SET yourcolumn = %s WHERE yourkey = %s"
val = (value, key)
mysql_cursor.execute(sql, val)
mysql_connection.commit()
# 更新redis中的数据
redis_client.set(key, value)
# 备份数据到mysql中并同步到redis中
def backup_to_mysql_and_sync_to_redis(key):
# 从mysql中获取数据
mysql_cursor = mysql_connection.cursor()
sql = "SELECT yourcolumn FROM yourtable WHERE yourkey = %s"
val = (key,)
mysql_cursor.execute(sql, val)
result = mysql_cursor.fetchone()
# 将数据写入redis中
if result:
redis_client.set(key, result[0])
# 查询数据时,先从redis中查询,如果不存在再从mysql中查询并写入redis
def get_data(key):
value = redis_client.get(key)
if value:
return value
else:
backup_to_mysql_and_sync_to_redis(key)
value = redis_client.get(key)
return value
请注意,上述代码仅为示例,具体的实现方式可能会因应用需求的不同而有所调整。