LSMT存储引擎
传统数据库:
- 计算层:SQL解析、查询优化、计划执行
- 存储层:
- AICD
- 屏蔽IO
数据库id增长方案: - UUID - AUTO-ID - redis的incr,考虑持久化 - 雪花算法
- 子结构
- SSTabke(Stored String Table),KV结构顺序排列的文件——不可修改
- MemTable:于内存中的数据结构
- log文件
LSMT和B+Tree
- 顺序写模型对于 SSD 设备更友好
- SST 不可修改的特性使得其能使用更加紧凑的数据排列和加上压缩
- 后台延迟 Compact 能更好利用 CPU 多核处理能力,降低前台请求延迟
Hbase
- 其直接存储在HDFS
RocksDB
- 批量WSL写入
- 并发MemTable更新
Java并发
volatile关键字
- 可见性
- 进制指令重排
- 不能保证原子性(
i++不是原子操作)
死锁:所有线程都阻塞
//例子:1
private static Integer count = 0;
//例子:2
//为每个线程构造一个实例 private static ThreadLocal<Integer> t = ThreadLocal.withInitial(() -> Integer.valueOf(10));
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 3; i++) {
new Thread(() -> {
count++;
}).start();
}
Thread.sleep(1000);
System.out.println("count : "+count);
}
- 使用局部变量可以提高线程的安全性
t.get()方法可以得到属于当前线程的Integer对象。可以看到无论线程中如何操作这个变量,它操作的其实都是属于当前线程的那个实例(局部变量)。
Futrue
--
实现类FutureTask,实现了Future和Runnable接口。
这个类的构造方法中可以传递一个Callable对象。Callable是一个封装了带有返回值方法的泛型类,返回值类型就是为泛型指定的类型。而Future就保存了Callable返回的这个结果。当完成上面的工作之后,就可以将FutureTask对象传到new Thread()构造器,并调用start()运行。
不常用,
Future可以保存异步计算结果
创建线程池
执行器Executors类有很多静态方法用来获取线程池
| 方法 | 描述 |
|---|---|
| newCachedThreadPool | 必要的时候会创建新的线程;池中的空闲线程会保留60秒 |
| newFixedThreadPool | 包含固定线程数的线程池;线程会一直保留 |
| newSingleThreadExecutor | 只包含一个线程,一次只能运行一个任务,排队执行 |
ExecutorService es = Executors.newFixedThreadPool(16);
//get()可以取出就是结果