Redis中的Lua

Redis中的Lua 一. Redis中的Lua脚本的作用 Redis中的Lua脚本主要解决复杂操作的原子性和性能优化两大核心问题。它允许你在Redis服务器端直接执行自定义的逻辑,而不是把数据拉到客户端处理后再写回去。 核心作用 1. 保证原子性操作 Redis执行Lua脚本时,脚本中的所有命令会作为一个整体被执行,中间不会被其他命令插入。这完美解决了多命令组合操作时的并发安全问题。 经典场景: 实现分布式锁、库存扣减、限流计数器等。比如秒杀场景下,检查库存、扣减库存、记录订单这三个操作必须原子执行,用Lua脚本就能确保数据一致性。 2. 减少网络开销 将多个Redis命令合并到一个Lua脚本中,原本需要多次网络请求的操作变成一次请求完成。数据在Redis服务器本地处理,避免了大量数据在客户端和服务器之间来回传输。 3.扩展Redis指令集 你可以用Lua实现Redis原生不支持的复杂业务逻辑。比如自定义数据结构操作、复杂条件判断、循环处理等,让Redis变成一个具备计算能力的"小数据库"。 4. 提高代码复用率 脚本可以被缓存到Redis服务器,客户端通过SHA1摘要重复调用,无需每次都发送完整的脚本代码。多个应用可以共享同一套脚本逻辑 总结 Redis Lua脚本让你能把多个操作打包成一个原子性的、在服务器本地执行的任务,既保证了数据一致性,又提升了性能。特别适合秒杀、分布式锁、计数器、复杂条件更新等需要"读-改-写"原子操作的场景。 二、Lua安装 windows下载地址 :https://luabinaries.sourceforge.net/ 三 、 Lua在Redis中最常用、最经典的几个应用场景 1. 在Redis中操作Lua脚本的常用命令 命令 作用 一句话解释 EVAL 执行给定的Lua脚本 直接把脚本和参数传给Redis运行一次。 SCRIPT LOAD 将脚本缓存到Redis 把脚本存到Redis里,会返回一个SHA1值作为“脚本ID”。 EVALSHA 根据SHA1值执行缓存的脚本 拿着“脚本ID”去执行之前存好的脚本,省流量,效率更高。 SCRIPT EXISTS 检查脚本是否已缓存 看看某个“脚本ID”对应的脚本还在不在Redis里。 SCRIPT KILL 终止正在运行的脚本 如果脚本执行太久卡住了,可以用这个命令尝试杀掉它。 SCRIPT FLUSH 清空所有缓存的脚本 一键清除Redis里缓存的所有脚本,操作要小心\-1。 2. 五大经典应用场景 分布式锁 这是Lua脚本在Redis中最经典的应用。获取锁和释放锁的多个步骤必须是一个原子操作,否则会出现并发问题。 获取锁:使用 SET NX PX 命令,一步到位地尝试设置一个带过期时间的键,保证只有一个客户端能拿到锁-8。 释放锁:释放锁时,需要先检查当前持有锁的客户端是否就是自己(通过一个唯一值比如UUID判断),然后再删除锁。这两个动作必须通过Lua脚本一起执行,才能避免误删别人的锁-2-8。 -- 安全的释放锁脚本 -- KEYS[1]: 锁的名称 -- ARGV[1]: 客户端的唯一标识 if redis....

March 12, 2024 · 2 min · Leanku

Redis分布式

Redis分布式 一、 Redis分布式概述 1. 什么是Redis分布式 Redis分布式是指将Redis数据分布到多个Redis节点上,通过集群方式提供更高性能、更大容量和更好可用性的解决方案。 1.2 为什么需要Redis分布式 数据量增长:单机内存容量有限 高并发需求:单机性能瓶颈 高可用性:避免单点故障 可扩展性:支持业务动态扩容 1.3 Redis分布式方案对比 方案 优点 缺点 使用场景 主从复制 部署简单,读写分离 写操作单点,故障需手动切换 读多写少,数据备份 Redis Sentinel 自动故障转移,高可用 配置复杂,扩容不便 生产环境高可用 Redis Cluster 数据分片,自动故障转移 客户端兼容性要求,迁移复杂 大数据量,高并发 二、 Redis分布式方案搭建 2.1 主从复制搭建 配置文件示例 主节点 (master.conf): port 6379 daemonize yes pidfile /var/run/redis_6379.pid logfile "/var/log/redis_6379.log" 从节点 (slave.conf): port 6380 daemonize yes pidfile /var/run/redis_6380.pid logfile "/var/log/redis_6380.log" slaveof 127.0.0.1 6379 启动命令 # 启动主节点 redis-server master.conf # 启动从节点 redis-server slave.conf 2.2 Redis Sentinel搭建 Sentinel配置文件...

March 12, 2024 · 3 min · Leanku

Mysql主从复制原理及保证数据一致性

Mysql主从复制原理及保证数据一致性 提升数据库的并发能力 提在实际工作中,我们常常将Redis作为缓存与MySQL来配合使用,当有请求的时候,首先会从缓存中进行查找,如果存在就直接取出,如果不存在再访问数据库。这样就提升了读取的效率,也减少了对后端数据库的访问压力。 此外,对于一般数据库应用而言,都是读多写少的,当数据库读取数据压力较大时,我们可以从成本较小的方案开始优化,可以首先考虑优化SQL和索引,其次就是缓存策略,最后才是主从架构。 主从复制的作用 读写分离。 在读多写少的情况下,可以采用读写分离,主库当做写库,然后根据实际需要,选择使用多个读库,分散读的压力,提高并发性。 数据备份。 主从复制其实就相当于一种热备份的机制。 实现高可用。 数据备份其实就是一种冗余机制,当主服务器出现故障是时,可以切换到从服务器上,提高服务器可用性。 主从复制原理 实际上主从同步的原理就是基于binlog进行数据同步的。在主从复制过程中,会基于3个线程来操作,一个主库线程,两个从库线程。 二进制日志转储线程是一个主库线程。 当从库线程连接的时候,主库可以将二进制日志发送给从库,当主库读取事件的时候,会在Binlog上加锁,读取完成之后,再将锁释放掉。 从库I/O线程会连接到主库,向主库发送请求更新Binlog。 这时从库的I/O线程就可以读取到主库的二进制日志转储线程发送的Binlog更新部分,并且拷贝到本地的中继日志。 从库SQL线程会读取从库中的中继日志,并且执行日志中的事件,将从库中的数据与主库保持同步。 总结起来就是三步: 步骤1:Master将写操作记录到二进制日志(binlog),这些记录叫做二进制日志事件(binary log events); 步骤2:Slave 将 Master 的 binary log events拷贝到它的中继日志(relay log); 步骤3:Slave重做中继日志中的事件,将改变应用到自己的数据库中。 搭建 TODO 此处省略,待补充 如何解决数据一致性问题 进行主从同步的内容是二进制日志,它是一个文件,在进行网络传输的过程中就一定会存在主从延迟,这样就可能造成用户在从库上读取的数据不是最新的数据,也就是主从同步中的数据不一致性问题。 方案一、异步复制 异步模式就是客户端提交COMMIT之后不需要等从库返回任何结果,而是直接将结果返回给客户端,这样做的好处是不会影响主库写的效率。 但这样可能会存在主库宕机,而Binlog还没有同步到从库的情况,也就是此时的主库和从库数据不一致。 这时候从从库中选择一个作为新主,那么新主则可能缺少原来主服务器中已提交的事务。所以,这种复制模式下的数据一致性是最弱的。 方案二、半同步复制 半同步复制的原理是在客户端提交COMMIT之后不直接将结果返回给客户端,而是等待至少有一个从库接收到了Binlog,并且写入到中继日志中,再返回给客户端。 这样做的好处是提高了数据的一致性,当然相比于异步复制来说,至少多增加了一个网络连接的延迟,降低了主库写的效率。 在MySQL5.7版本中还增加了一个参数,可以对应答的从库数量进行设置,默认为1,也就是说只要有1个从库进行了响应,就可以返回给客户端。如果将这个参数调大,可以提升数据一致性的强度,但也会增加主库等待从库响应的时间。 方案三、组复制 异步复制和半同步复制都无法最终保证数据的一致性问题,半同步复制是通过判断从库响应的个数来决定是否返回给客户端,虽然数据一致性相比于异步复制有提升,但仍然无法满足对数据一致性要求高的场景。 组复制技术MGR很好地弥补了这两种复制模式的不足,它是MySQL在5.7.17版本中推出的一种新的数据复制技术,是基于Paxos协议的状态机复制。 原文链接:

March 12, 2024 · 1 min · Leanku

PHP面向对象

PHP面向对象 面向对象程序设计实际上就是对现实世界的对象进行建模操作。面向对象程序设计的特征主要可以概括为封装、继承和多态 特性 封装 指将对象的属性和方法封装在一起,使得外部无法直接访问和修改对象的内部状态。通过使用访问控制修饰符(public、private、protected)来限制属性和方法的访问权限,从而实现封装 例如,计算机的主机是由内存条、硬盘、风扇等部件组成,生产厂家把这些部件用一个外壳封装起来组成主机,用户在使用该主机时,无需关心其内部的组成及工作原理 继承 指可以创建一个新的类,该类继承了父类的属性和方法,并且可以添加自己的属性和方法。通过继承,可以避免重复编写相似的代码,并且可以实现代码的重用。 例如,已经描述了汽车模型这个类的属性和行为,如果需要描述一个小轿车类,只需让小轿车类继承汽车模型类,然后再描述小轿车类特有的属性和行为,而不必再重复描述一些在汽车模型类中已有的属性和行为 多态 程序中的多态是指一种行为对应着多种不同的实现。指可以使用一个父类类型的变量来引用不同子类类型的对象,从而实现对不同对象的统一操作。多态可以使得代码更加灵活,具有更好的可扩展性和可维护性。 例如,在一般类中说明了一种求几何图形面积的行为,这种行为不具有具体含义,因为它并没有确定具体几何图形;在特殊类(如三角形、正方形、梯形)中都继承了一般类的求面积的行为,可以根据具体的几何图形重新定义求面积行为。 在 PHP 中,多态可以通过实现接口(interface)和使用抽象类(abstract class)来实现。 类与对象 在PHP中把具有相同属性和行为的对象看成同一类,把属于某个类的实例称为某个类的对象。例如学生小千与小锋是两个不同的对象,两者有共同的属性(如学号、成绩等),也有相同的行为(如选课、显示成绩等),因此两者同属于学生类 类 − 定义了一件事物的抽象特点。类的定义包含了数据的形式以及对数据的操作。 对象 − 是类的实例。 成员变量 − 定义在类内部的变量。该变量的值对外是不可见的,但是可以通过成员函数访问,在类被实例化为对象后,该变量即可成为对象的属性。 成员函数 − 定义在类的内部,可用于访问对象的数据。 继承 − 继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。 父类 − 一个类被其他类继承,可将该类称为父类,或基类,或超类。 子类 − 一个类继承其他类称为子类,也可称为派生类。 多态 − 多态性是指相同的函数或方法可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。 重载 − 简单说,就是函数或者方法有同样的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。 抽象性 − 抽象性是指将具有一致的数据结构(属性)和行为(操作)的对象抽象成类。一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容。任何类的划分都是主观的,但必须与具体的应用有关。 封装 − 封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内。 构造函数 − 主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。 析构函数 − 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做"清理善后" 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。 类定义 类使用 class 关键字后加上类名定义。 类名后的一对大括号({})内可以定义变量和方法。 类的变量使用 var 来声明, 变量也可以初始化值。 函数定义类似 PHP 函数的定义,但函数只能通过该类及其实例化的对象访问。 <?...

March 11, 2024 · 2 min · Leanku

PHP魔术方法

PHP魔术方法 魔术方法是一种特殊的方法,当对对象执行某些操作时会覆盖 PHP 的默认操作。 PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用。 __construct(),类的构造函数。 PHP 允许开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。 __destruct(),类的析构函数。 析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。 __call(),在对象中调用一个不可访问方法时调用。 __callStatic(),用静态方式中调用一个不可访问方法时调用 __get(),获得一个类的成员变量时调用。 读取不可访问(protected 或 private)或不存在的属性的值时,__get() 会被调用 __set(),设置一个类的成员变量时调用。 在给不可访问(protected 或 private)或不存在的属性赋值时,__set() 会被调用。 __isset(),当对不可访问属性调用isset()或empty()时调用。 当对不可访问(protected 或 private)或不存在的属性调用 isset() 或 empty() 时,__isset() 会被调用。 __unset(),当对不可访问属性调用unset()时被调用。 当对不可访问(protected 或 private)或不存在的属性调用 unset() 时,__unset() 会被调用。 __sleep(),执行serialize()时,先会调用这个函数。 __sleep() 方法常用于提交未提交的数据,或类似的清理操作。 __wakeup(),执行unserialize()时,先会调用这个函数。 __wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。 __toString(),类被当成字符串时的回应方法 __invoke(),调用函数的方式调用一个对象时的回应方法 __set_state(),调用var_export()导出类时,此静态方法会被调用。 __clone(),当对象复制完成时调用 __autoload(),尝试加载未定义的类 __debugInfo(),打印所需调试信息 参考文章: PHP: 魔术方法 - Manual

March 10, 2024 · 1 min · Leanku

MySQL主从复制

MySQL 分库分表 + 主从复制 一、主从复制 1. 环境说明 1个master节点,2个slave节点 mysql-master mysql-slave1 mysql-slave2 此处使用docker启动多个 MySQL 容器,为每个容器挂载配置文件 docker run -d --name mysql-master -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 mysql:8.0 docker run -d --name mysql-slave1 -e MYSQL_ROOT_PASSWORD=root -p 3307:3306 mysql:8.0 docker run -d --name mysql-slave2 -e MYSQL_ROOT_PASSWORD=root -p 3308:3306 mysql:8.0 创建配置文件目录 mkdir -p ~/mysql/master ~/mysql/slave1 ~/mysql/slave2 2. 修改配置 master的 my.cnf (~/mysql/master/my.cnf) [mysqld] server-id=1 log_bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON slave1 的 my.cnf(~/mysql/slave1/my.cnf) [mysqld] server-id=2 relay_log_recovery=ON read_only=ON super_read_only=ON gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON slave2 的 my....

February 20, 2024 · 2 min · Leanku

Mysql的一些常见题

Mysql的一些常见题 请写出数据类型(int char varchar datetime text)的意思;请问 varchar 和 char有什么区别? Int 整数char 定长字符 Varchar 变长字符 Datetime 日期时间型Text 文本型 Varchar与char的区别 char是固定长度的字符类型,分配多少空间,就占用多长空间。Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作,所以效率比char类型低。 MyISAM和 InnoDB 的基本区别?索引结构如何实现? A、MyISAM类型不支持事务,表锁,易产生碎片,要经常优化,读写速度较快,适合用于频繁查询的应用; B、InnoDB类型支持事务,行锁,有崩溃恢复能力,读写速度比MyISAM慢,适合于插入和更新操作比较多的应用,空间占用大,不支持全文索引等。创建索引:alert table tablename add index 索引名 (字段名) 什么是事务?及其特性? 答:事务:是一系列的数据库操作,是数据库应用的基本逻辑单位。 事务特性:A、原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。B、一致性或可串性。事务的执行使得数据库从一种正确状态转换成另一种正确状态C、隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,D、持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。 或者这样理解:事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。 什么是锁? 答:数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。 加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。 基本锁类型:锁包括行级锁和表级锁 索引的作用?和它的优点缺点是什么? 索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。 怎么防止sql注入? 1)过滤掉一些常见的数据库操作关键字:select,insert,update,delete,and,*等,或者通过系统函数:addslashes(需要被过滤的内容)来进行过滤。 2)在PHP配置文件中 Register_globals=off;设置为关闭状态 //作用将注册全局变量关闭。 比如:接收POST表单的值使用$_POST[‘user’],如果将register_globals=on;直接使用$user可以接收表单的值。 3)SQL语句书写的时候尽量不要省略小引号(tab键上面那个)和单引号 4)提高数据库命名技巧,对于一些重要的字段根据程序的特点命名,取不易被猜到的 5)对于常用的方法加以封装,避免直接暴漏SQL语句 6)开启PHP安全模式 Safe_mode=on; 7)打开magic_quotes_gpc来防止SQL注入 Magic_quotes_gpc=off;默认是关闭的,它打开后将自动把用户提交的sql语句的查询进行转换,把’转为',这对防止sql注入有重大作用。 因此开启:magic_quotes_gpc=on; 8)控制错误信息 关闭错误提示信息,将错误信息写到系统日志。 9)使用mysqli或pdo预处理。 数据库优化策略? 合理的表设计。 依据三范式,设计表. ​ 三范式:1.原子性,每个字段都是不可在分的。 在1方式的基础上,表中每一列必须有唯一性,其他字段依赖主键。 在2方式的基础上,表中的每一列只与主键直接相关,而不是间接相关。 选择合适的字段。 I.尽量使用TYPEINT、SMALLINT、MEDIUM_INT代替INT的使用,一般索引,并且是字段递增,可以考虑设置为UNSIGNED. ​ II.使用枚举代替字符串类型。 ​ III.将少null的使用,null很难优化,并且还占用额外的空间。...

February 20, 2024 · 2 min · Leanku

PHP常见题

PHP常见题 1. 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰。主要特征:封装、继承、多态。 2. SESSION 与 COOKIE的区别是什么,请从协议,产生的原因与作用说明? A、http无状态协议,不能区分用户是否是从同一个网站上来的,同一个用户请求不同的页面不能看做是同一个用户。 B、SESSION存储在服务器端,COOKIE保存在客户端。Session比较安全,cookie用某些手段可以修改,不安全。 Session依赖于cookie进行传递。禁用cookie后,session不能正常使用。 Session的缺点:保存在服务器端,每次读取都从服务器进行读取,对服务器有资源消耗。Session保存在服务器端的文件或数据库中,默认保存在文件中,文件路径由php配置文件的session.save_path指定。Session文件是公有的。 3. HTTP 状态中302、403、 500代码含义? 一二三四五原则:(即一:消息系列;二:成功系列;三:重定向系列;四:请求错误系列;五:服务器端错误系列。) 302:临时转移成功,请求的内容已转移到新位置 403:禁止访问 500:服务器内部错误 401:代表未授权。 4. 请写出数据类型(int char varchar datetime text)的意思;请问 varchar 和 char有什么区别? Int 整数char 定长字符 Varchar 变长字符 Datetime 日期时间型Text 文本型 Varchar与char的区别 char是固定长度的字符类型,分配多少空间,就占用多长空间。Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作,所以效率比char类型低。 5. MyISAM和 InnoDB 的基本区别?索引结构如何实现? A、MyISAM类型不支持事务,表锁,易产生碎片,要经常优化,读写速度较快,适合用于频繁查询的应用; B、InnoDB类型支持事务,行锁,有崩溃恢复能力,读写速度比MyISAM慢,适合于插入和更新操作比较多的应用,空间占用大,不支持全文索引等。创建索引:alert table tablename add index 索引名 (字段名) 6. isset() 和 empty() 区别 isset判断变量是否存在,可以传入多个变量,若其中一个变量不存在则返回假;empty判断变量是否为空为假,只可传一个变量,如果为空为假则返回真。 7. 请说明 PHP 中传值与传引用的区别。什么时候传值什么时候传引用? 按值传递:函数范围内对值的任何改变在函数外部都会被忽略按引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改优缺点:按值传递时,php必须复制值。特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作。按引用传递则不需要复制值,对于性能提高很有好处。 8. 在PHP中error_reporting这个函数有什么作用? 设置PHP的报错级别并返回当前级别。 9. 现在编程中经常采取MVC三层结构,请问MVC分别指哪三层,有什么优点? MVC三层分别指:业务模型、视图、控制器,由控制器层调用模型处理数据,然后将数据映射到视图层进行显示,优点是:①可以实现代码的重用性,避免产生代码冗余;②M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式 10. 在程序的开发中,如何提高程序的运行效率? A、优化SQL语句,查询语句中尽量不使用select *,用哪个字段查哪个字段;少用子查询可用表连接代替;少用模糊查询;...

February 20, 2024 · 2 min · Leanku

Redis的一些常见题

Redis的一些常见题 redis数据类型及应用场景 见 Redis的五种数据类型及使用场景 redis持久化及过期策略 见 Redis持久化及过期删除策略 redis 常见问题及解决方案 缓存雪崩:同一时间大量缓存失效,导致请求直接查询数据库,数据库内存和CPU压力增加甚至宕机 解决: 热点数据永不过期或者分布到不同实例,降低单机故障问题 缓存时间添加随机数,防止大量缓存同时失效 做二级缓存或者双缓存,A为原始缓存 短时效,B为备份缓存 ,长期有效。更新时候双写缓存 缓存穿透:缓存和数据库都没有数据,大量请求下,所有请求直接击穿到数据库,导致宕机。 解决: 布隆过滤器:长度为m的位向量或者位列表组成(仅包含0或1位值的列表) 使用多个不用的hash函数,产生多个索引值,填充对应多个位置的值为1 布隆过滤器可以检查值是 “可能在集合中” 还是 “绝对不在集合中” 可能误判但是基础过滤效率高 极端情况,当布隆过滤器没有空闲位置的时候每次查询返回true 空缓存(短时效) 业务层参数过滤 缓存击穿:数据库中有数据,但是缓存突然失效之后发生大量请求导致数据库压力增加甚至打垮宕机 解决: 热点数据永不过期 互斥锁:获取锁之后不管成功还是失败都要释放锁 Redis主从复制原理 Redis 在复制时底层采用的是 psync 命令完成的数据主从同步,同步主要分为:全量复制和增量复制两种 全量复制:顾名思义也就是一次性把主节点数据全部发送给从节点,所以这种情况下,当数据量比较大时,会对主节点和网络造成很大的开销。 部分复制:用于处理主从复制时因网络中断等原因造成数据丢失的场景。当从节点再次和主节点连接时,主节点会补发丢失的数据。因为是补发,所以在发送的数据量一定是小于全量的数据。 详细见 Redis的一些常见题 Redis缓存和数据库数据一致性问题: 读数据 尝试查询缓存,存在缓存则直接返回数据 缓存不存在时则查询数据库,并保存到缓存(合适设置过期时间),返回数据 写数据 先更新缓存再更新数据库 或者 先删除缓存再更新数据库 先更新数据库再更新缓存 或者 先更新数据库再删除缓存 使用删除还是更新? 这里无非是删除还是更新Redis,直接删除的方式比较简单,在下一次查询时会生成缓存(更推荐);更新缓存则相较复杂 先操作Redis还是先操作数据库? 先操作数据库 (推荐) 流程:先更新数据库,再删除缓存 问题:比如线程1执行写操作(修改数据库->删除缓存),线程2执行读操作(查询缓存->旧数据),就会出现旧数据返回,或者删除缓存失败也会返回旧数据 先操作缓存 流程:修改操作先删除缓存再修改数据库 问题: 比如线程1去执行写操作: (删除缓存->更新数据库)同时有线程2执行读操作(查询缓存(未查到缓存)->查数据库->保存到缓存)因为数据库更新有可能网络延迟等问题,这里保存到缓存的数据就是旧的数据,只有再过期之后才会读到新数据 解决方案: (延迟双删)在数据库更新之后再进行一次缓存删除(加适当延迟,比如延迟500ms),这时再有查询过来也会查询到数据库并保存到缓存。但是线程2在这个删除缓存500ms内请求仍然可能会出现一次获取到旧数据 (推荐方式)

February 20, 2024 · 1 min · Leanku

ShardingSphere 使用指南

ShardingSphere 使用指南 一、介绍 Apache ShardingSphere 是一个开源的 分布式数据库中间件生态,支持 分库分表、读写分离、数据加密、影子库 等功能。它的定位是 数据库增强计算层,让你在不修改(或少量修改)应用代码的情况下,实现复杂的数据分片与治理。 核心组件: ShardingSphere-JDBC:客户端 SDK,直接在应用中引入。 ShardingSphere-Proxy:中间件代理层,应用通过 MySQL 协议访问,无需修改业务代码。 ShardingSphere-Sidecar:面向 K8s 的云原生数据库 Mesh。 二、适用场景 分库分表:数据量过大,单表行数超过 1千万~1亿,单库容量超限时。 读写分离:主库写、从库读,提升查询性能。 柔性事务:分布式场景下保证一致性(支持 Seata、XA)。 数据加密:对敏感字段(手机号、身份证号)自动加密存储,解密查询。 影子库:A/B 测试或灰度发布。 三、 配置方式 以 ShardingSphere-Proxy 为例(最常用于 PHP 项目)。 3.1 部署 Proxy wget https://downloads.apache.org/shardingsphere/5.4.2/apache-shardingsphere-5.4.2-shardingsphere-proxy-bin.tar.gz tar -zxvf apache-shardingsphere-5.4.2-shardingsphere-proxy-bin.tar.gz cd apache-shardingsphere-5.4.2-shardingsphere-proxy-bin 配置文件路径: conf/server.yaml # 全局配置(身份认证、元数据) conf/config-sharding.yaml # 分库分表配置 3.2 示例配置(分库分表 + 读写分离) server.yaml (全局配置) authentication: users: root: password: root123 # 设置登录 ShardingSphere-Proxy 的账号和密码 authorizedSchemas: ds_sharding # 指定该用户可访问的逻辑库(schema) props: sql-show: true # 开启 SQL 打印,方便调试时查看 Proxy 最终路由后的真实 SQL config-sharding....

February 20, 2024 · 2 min · Leanku