在 C++ 中,使用 new/delete 方式进行对象内存管理分配和回收,底层分为两个步骤:
要建立分布式系统,一般有两个思考方向:
哈希取余
的方式计算当前数据的落点,即每个节点只保存有一部分的数据单纯使用hash
算法的弊端在于,它需要向当前节点数进行取余操作,这就导致了如果节点数量发生扩容或者缩容,则计算出的数据落点会不一样,因此需要进行洗数据。
不过如果节点只是作为缓存用,即只用作数据读取而对数据的修改会直接写回后端数据库等具有持久化的服务进行落地,那么扩容/缩容后的真实数据是可以从持久化服务进行恢复的,在扩容或者缩容之后对原数据的恢复倒不是什么大问题。比方说原有的缓存系统有三个缓存节点,那么现在扩容到四个节点,假设之前有份数据的缓存落点是在节点三,而扩容后落点是在节点四。那么在读取时由于节点四没有该份数据,因此会直接从后端的数据库加载并存入到节点四,而节点三原有的旧数据则可以依赖于缓存过期的自动删除,再者就算没有设计删除过期缓存的功能,这些脏数据也顶多只是占用内存,不会再被访问到。当然如果在旧数据过期之前又进行了一次扩容/缩容,那么就有可能会使读取到过期的脏数据,造成异常,所以对缓存设计过期时间是有很大的必要性的。
如果节点是作为数据存储节点使用,那么上面提到的hash
算法的问题就会有影响了,每次扩容或者缩容时都需要进行大规模的数据迁移。
添加全局锁的语句为:
flush tables with read lock
全局锁的作用是将整个数据库锁定为只读状态
,这时候其他线程执行以下操作都会被阻塞:
对于当前线程来说,当执行上述的语句时不会进入阻塞状态,而是会产生锁冲突报错。
mysql> select * from test_table where id = 1 for update;
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
要释放全局锁,则需要执行:
unlock tables
先从 Redis 架构入手看下在系统底层是如何管理过期键值对的
当我们启动 Redis 时,会创建一个redisServer
结构体,保存了当前服务器的信息,以及当前所有的数据库信息
struct redisServer {
// ...
redisDb *db; // 数据库列表
// ...
int dbnum; // 数据库数量
// ...
}
Redis 默认的数据库数量是16
个,在配置redis/redis.conf
中可进行配置修改,可以通过下面这张图表示:
注:Redis 数据库是无法指定名字的,只能根据数组下标表示,通过 SELECT xx 的方式进行切换,默认连接数据库是 0 号数据库
Basic Paxos 论述的是在分布式架构下,对于一个变量同时出现不同的值时,如何对该变量的值形成共识性,是一种理论研究模型。注意后面分析中探讨的是如何对这不同的值达成共识的过程
我们一般说 Python 是一门解释型的语言,因为它可以通过Python code.py
的方式直接运行代码,而无需像编译型语言如 C++ 那样需要先经过编译才可以运行
我们来做个测试:
## main.py
def Fun1():
print("Python 是解释型语言吗?")
if __name__ == '__main__':
Fun1()
linux 系统针对不同的场景,实现了以下几种 IO 类型:
Buffered IO(默认方式)
每次读取都需要经过 PageCache 缓存,这种方式的效率性能最高
Direct IO
读取不经过 PageCache 缓存,调用系统应用时需要指定 O_DIRECT 参数。因为没有经过内存缓存的缘故,虽然数据本身会直接落地到磁盘,但是一些文件的其他元数据还是会缓存在内存中,因此我们在使用 Direct IO 时,还需要配合使用fsync
进行强制文件写入磁盘。
这种方式是应用在某些具有自己缓存方案的场景,如数据库自己设计了一套缓存方案,因此需要使用 Direct IO 来加速数据写入磁盘的速度
AIO
异步IO,linux 的 AIO 只能指定为 Direct IO 的形式,即不能经过 PageCache