redis 事务 持久化 主从架构

事务表示一组动作, 要么全部执行, 要么全部不执行。

ACID :保证执行多个指令的时候,要么都执行,要么都不执行,要么都成功,要么都没有成功 这个是数据库的事务

特点:原子性(Atomicity) 一致性(Consistency) 隔离性(Isolation) 持久性(Durability)

但是redis事务的特点是:提交--没有回滚,提交就提交了 ,成功或者不成功,只会返回一个结果

redis:

  • Multi:标记事务的开始;
  • Exec:执行事务的commands队列;
  • Discard:结束事务,并清除commands队列;

redis里面使用普通事务,没有锁===

建议:如果要使用redis的事务,则需要和Watch方法一起使用,而且最好,监听的这些字段都包含在所有的key里面。。 小菜鸟玩事务,大神搞lua

复制代码
public class TransAction
    {
        public static void Show()
        {
            try
            {

                //事务模式 
                using (RedisClient client = new RedisClient("127.0.0.1", 6379))
                {
                    //删除当前数据库中的所有Key  默认删除的是db0
                    client.FlushDb();
                    //删除所有数据库中的key 
                    client.FlushAll();

                    client.Set("a", "1");
                    client.Set("b", "1");
                    client.Set("c", "1");

                    ////获取当前这三个key的版本号 实现事务
                    client.Watch("a","b","c");//这里需要监听所有的key
                    //client.Watch("c");//如果单独监听一个了,指定处理对应key上的事务
                    using (var trans = client.CreateTransaction())
                    {
                        trans.QueueCommand(p => p.Set("a", "3"));
                        trans.QueueCommand(p => p.Set("b", "3"));
                        trans.QueueCommand(p => p.Set("c", "3"));

                        var flag = trans.Commit();
                        Console.WriteLine(flag);
                    }
                    //根据key取出值,返回string
                    Console.WriteLine(client.Get<string>("a") + ":" + client.Get<string>
                    ("b") + ":" + client.Get<string>
                    ("c"));
                    Console.ReadLine();
                }


            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine();
        }
    }
复制代码
Redis提供了简单的事务, 之所以说它简单, 主要是因为它不支持事务中的回滚特性, 同时无法实现命令之间的逻辑关系计算, 当然也体现了Redis的“keep it simple”的特性。
Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码
形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程
序提供灵活的扩展和定制功能。
 
Lua脚本功能为Redis开发和运维人员带来如下三个好处:
·Lua脚本在Redis中是原子执行的, 执行过程中间不会插入其他命令。
·Lua脚本可以帮助开发和运维人员创造出自己定制的命令, 并可以将这些命令常驻在Redis内存中, 实现复用的效果。
·Lua脚本可以将多条命令一次性打包, 有效地减少网络开销。
 
高并发超卖场景:(一般是先查数据库库存>0的情况下订单+1,库存-1)
简单c#用于处理高并发秒杀的问题列子:
复制代码
public class LuaTest
    {
        public static void Show()
        {

            using (var client = new RedisClient("192.168.1.211", 6379))
            {

                //Console.WriteLine(client.ExecLuaAsString(@"return  redis.call('get','name')"));

                //库存
                //Console.WriteLine(client.ExecLuaAsString(@"redis.call('set','number','10')"));
                var lua = @"local count = redis.call('get',KEYS[1])
                                        if(tonumber(count)>=0)
                                        then
                                            redis.call('INCR',ARGV[1])
                                            return redis.call('DECR',KEYS[1])
                                        else
                                            return -1
                                        end";
                Console.WriteLine(client.ExecLuaAsString(lua, keys: new[] { "number" }, args: new[] { "ordercount" }));


            }
        }
    }
复制代码

C#限流的例子

复制代码
### 限流lua代码如下
local times = redis.call('incr',KEYS[1])
if times == 1 then
  redis.call('expire',KEYS[1], ARGV[1])
end
 
if times > tonumber(ARGV[2]) then
  return 0
end
return 1
复制代码
复制代码
/// <summary>
/// 滑窗式限流 利用redis的Zset类型
/// </summary>
/// <returns></returns>
public bool LimitFlow()
{
    DateTime currentTime = DateTime.Now;
    using (IRedisClient client = redisService.GetRedisClient())
    {
        // 判断是否存在响应的key
        if (client.ContainsKey("服务名称"))
        {
            //获取前一秒和当前秒时间类的集合总数量
            //此数量表示的就是请求数量
            int count = client.GetRangeFromSortedSetByLowestScore("服务名称", currentTime.AddSeconds(-1).ToFileTimeUtc(), currentTime.ToFileTimeUtc()).Count;
            // 8表示的是限流的数量
            //如果请求数量大于限流数量,则返回false,可以拒绝请求
            if (count != null && count >8)
            {
                return false;
            }
        }
        //如果是第一次获取请求数量
        //或者满足限流限制,则返回true,然后给Zset中添加一次请求数量,分数就是当前的时间戳
        client.AddItemToSortedSet("服务名称", Guid.NewGuid().ToString(), currentTime.ToFileTimeUtc());
        return true;
    }

}
复制代码

 

可以把lua理解成数据存储过程,但是实质不一样,而且lua具有原子性,而且性能要比我们直接操作指令性能要高---lua是c语言编写的,redis也是c语言编写,不存在编译过程

持久化

快照的方式(RDB)---每次都去抓拍一下全面貌 每次都全量备份

文件追加方式(AOF)--在之前的基础上追加

RDB机制:

RDB其实就是把数据以快照的形式保存在磁盘上。什么是快照呢,你可以理解成把当前时刻的数据拍成一张照片保存下来。

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb

既然RDB机制是通过把某个时刻的所有数据生成一个快照来保存,那么就应该有一种触发机制,是实现这个过程。对于RDB来说,提供了三种机制:save、bgsave、自动化。我们分别来看一下

查看默认配置命令 config get  save :

指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合

Redis 默认配置文件中提供了三个条件:

save 900 1

save 300 10

save 60 10000

分别表示 900 秒(15 分钟)内有 1 个更改,300 秒(5 分钟)内有 10 个更改以及 60 秒内有 10000 个更改。

手动备份策略:

1.save: 阻塞线程--- 因为执行这个指令的线程就是redis里面唯一的那个执行指令的线程-

当你备份大量的数据的时候,如果耗时比较长,则当有其他客户端发送指令的时候,会卡主

2.bgsave: 单独的线程,后台专门有一个线程去实现备份。

这个后台的就是专门来根据我们的配置文件里策略然后去备份数据文件

底层原理: 有一个定时器,就是不停的计算我们阈值。每一次bgsave之后,要把计数器清0===

优势:备份缓慢,但是重启加载数据性能比较快。。。

 

 

文件追加方式(AOF):

查看aof是否开启命令 config get appendonly ,默认是没开启的

打开 redis.conf  修改以下参数:

appendonly  yes        (默认no,关闭)表示是否开启AOF持久化:

持久化的文件名为:appendonly.aof

AOF持久化策略(默认每秒):

  appendfsync always (同步持久化,每次发生数据变更会被立即记录到磁盘,性能差但数据完整性比较好)  只要有读写就会执行同步

  appendfsync everysec (异步操作,每秒记录,如果一秒钟内宕机,有数据丢失) 1s钟的周期 一般转字这一种

  appendfsync no (将缓存回写的策略交给系统,linux 默认是30秒将缓冲区的数据回写硬盘的)这种操作最不可靠

 

日志追加:基本都是顺序读写//本身要比我们操作关系型数据库要快(mysql==)

优点是:文件可读行高,每次都是追加修改的东西,备份比较快,但是当服务重启的时候,加载数据的时候比较慢 上面是快照现在不是了----

如果rdb和aof都开启了,则默认首先加载aof文件,为了保证数据的尽可能完整性。

aof 重写问题:当数据文件到达一个阈值的时候,,我们的文件会继续重写变成一个小文件。(当AOF文件的大小超过了配置所设置的阙值时,Redis就会启动AOF文件压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof)

两者的优缺点:

rdb:备份慢,启动快

aof:备份快,启动慢

redis..4X 版本之后,混合模式---(也就是把两个可以混合使用) 混合模式【备份,启动快】 :   备份的时候,我通过aof备份,我还原的时候根据rdb..

aof--文件重写的问题---到数据大的时候,

当我们进行aof操作的时候,把aof文件变成rdb,然后之后的操作直接取做日志追加。。

默认的情况下,你要你开启了aof则,混合默认自动打开 配置文件中  : aof-use-rdb-preamble yes

混合模式的文件--包含aof和rdb; aof打开的同时混合默认打开,如何手动调用呢 使用命令bgrewriteaof

情况分析:

如果要redis的性能非常高,就不要持久化

如果要保证数据的完整性,要根据自己的业务来选择不同的持久化策略,一般情况都是使用混合模式

第一次配置的时候,切记吧aof打开(默认开启混合模式)

主从架构:
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器,主从是哨兵和集群模式能够
实施的基础。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点
到从节点。(读写分离,主节点写,从节点读)
主从架构一般有两种方式,一种是一主多从,一种是树状结构
主从搭建参考:https://www.cnblogs.com/carrychan/p/9396997.html
演示docker下搭建的方式:
删除容器 docker rm -f xx   设置从节点的主节点: slaveof  host port     查看主从关系:info  replication  
取消成为任何服务器的从服务器  salveof no one 
从服务器设置只读  config set slave-read-only yes

docker run -d -p 5001:6379 --name redis1 redis 主

docker run -d -p 5002:6379 --name redis2 redis 从

docker run -d -p 5003:6379 --name redis3 redis 从

docker exec -it redis1 /bin/bash     ====》 redis-cli  ===>

docker exec -it redis2 /bin/bash     ====》 redis-cli  ===> slaveof  192.168.1.211 5001  ===》info  replication

docker exec -it redis3 /bin/bash    ====》 redis-cli   ===> slaveof  192.168.1.211 5001 ===》info  replication

 

主从是实现读写分离,然后主节点会把数据同步到从节点里面

用法是实现高可用,主节点宕机了,从节点可以替换主节点,不是自动替换,需要程序员修改代码,改ip地址和端口,或者应该是用keeplive 用vip地址来高可用。。。主从是不会自动切换--如果要自动切换要使用哨兵。。。

注意点:一般情况下,我们使用主从的时候,防止数据不一致,从节点只能读,不让他写,

默认从节点不会进行写操作。。。 所以当主节点宕机了,我们需要改代码,收到去修改redis的配置。。

redis多线程和线程的区别--redis 6.X 功能点比较全---

 

 
5
6
 
1
posted @   根仔  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示