一、事务
Redis的事务相对不是很完善,下面通过实例来看一下redis事务的问题在哪?事务正常执行:

事务执行出现问题:

以上实践可以看出redis虽然有事务,但是事务的机制并不完善,这是需要改进的地方。
一旦是数据库就会涉及到并发的问题,一般是使用锁类解决并发问题,锁分为悲观锁和乐观锁。在redis使用事务和watch监听一起达到乐观锁的效果,实例的完成需要开启两个会话。
实例:左侧为session2,右侧为session1

1、Session1添加监听,开启事务
2、session2中对age进行修改
3、session1中添加事务队列,修改age
4、执行事务,获取age的值
在session1中对age添加了监听,在监听后如果age的值被改变session1中对age再次做修改则无法提交。二、发布订阅消息
存储引擎
Cassandra使用了一种类似于日志结构合并树的存储结构,而不是像传统关系型数据库那样使用B-Tree。Cassandra避免写之前读。写前读,尤其是大型的分布式系统中,可能导致读取性能的延迟和其他问题。例如,两个客户端同时读。一个以覆盖的方式更新A,另一个以覆盖的方式更新B,同时删除A的更新。这种竞争条件会导致模棱两可的查询结果—虽然更新都是对的。
在Cassandra中为了避免写前读,存储引擎组在内存中进行插入和更新操作,然后在间隔的时候,依次将数据以追加的模式写入磁盘。一旦写入磁盘,数据就是不可变的,而且永远不会覆盖。读取数据需要结合这些不可变的、顺序写入的数据,以此发现正确的查询结果。你可以在写之前使用轻量级事务(LWT)来检查数据的状态。然而,此功能只被推荐用于有限的场合。
日志结构引擎避免了覆盖,使用了顺序IO来更新数据,对于写数据到固态硬盘和普通硬盘来说,是至关重要的。在HDD上,随机写比顺序写涉及到更多的查找操作。所导致的害处是实在的。由于Cassandra顺序写不可改变的文件,因此避免了写放大和磁盘故障,数据库容纳便宜的,消费者固态硬盘尤其好。在很多其他数据库上,写入放大是在SSD上是一个问题。
Cassandra如何读和写数据
Understanding howCassandra stores data.
要想管理和访问Cassandra的数据,理解Cassandra如何存储数据是非常重要的。hinted handoff的特性增加了Cassandra的性能,而且ACID(原子性,一致性,隔离性,持久性)的非一致性的数据库属性是理解读和写的关键概念。在Cassandra里,一致性的意思是如何保持最新,和在所有副本上的行的数据保持同步。
用于开发数据存储和索引的应用程序的客户端工具和应用编程接口(API)都是可用的。
数据如何写?
Understand how Cassandrawrites and stores data.
Cassandra在写路径上处理数据分为好几个阶段,以立即写日志开始,以写数据到磁盘结束。
? 写数据日志至commit log
? 写数据至memtable
? 从memtable刷新数据
? 存储数据值磁盘的SSTables
日志写入和memtable存储
当一个写发生时,Cassandra把数据存储到内存中的一个叫做memtable的结构里,而且为了提供可配置的持久化,它也将写入到磁盘的commit log里。Commit log接收Cassandra节点的每一个写操作,这些持久化的写操作永久存在,即使节点出现故障。Memtable是一个数据分区的写回缓存,Cassandra通过key查找。Memtable存储已排好序的写操作,直到达到配置的限制,然后再刷新。
从memtable刷新数据
刷新数据,Cassandra会按照memtable排序的顺序把数据写入磁盘。同时一个分区索引也会在磁盘上被创建,可以把token值映射到磁盘的某个位置上。当memtable的内容超过了配置好的阈值或者commit log的空间超过了commitlog_total_space_in_mb,这时memtable会进入一个会刷新到磁盘的队列中。该队列可以使用cassandra.yaml文件里的memtable_heap_space_in_mb或者memtable_offheap_space_in_mb来配置。如果将要刷新的数据超过了memtable_cleanup_threshold的值,Cassandra会阻塞写操作,直到下一个刷新成功。你可以使用
nodetool flush或者nodetooldrain(不需要监听其他节点,刷新memtables)直手动刷新一个表。为了减少commit log的重播时间,推荐最佳实践是在你启动节点之前刷新memtables。如果一个节点停止工作,在它停止之前重新提交commit log恢复memtable写。
commit log里的数据在相应的memtable里的数据刷新到磁盘的SSTable里以后,会进行合并。
Storingdata on disk in SSTables
每一个表都维护着一个Memtables和SSTables。commit log是所有的表共享的。SSTables是不可变的,在memtable刷新过后不会再重新写入。因此,一个分区通常保存在多个SSTable文件里。大量其他的SSTable结构存在着,以协助读操作。

对于每一个SSTable,Cassandra会创建这些结构:
数据 (Data.db)
SSTable的数据。
主要索引 (Index.db)
行键的索引,有指针指向他们在数据文件中的位置
Bloom过滤器(Filter.db)
内存中存储的一个结构,在数据进入磁盘的SSTables之前检查数据是否存在于memtable里。
Compression信息(CompressionInfo.db)
一个文件,包含未压缩的数据长度,块偏移量和其他的压缩信息。
统计 (Statistics.db)
统计SSTable的内容元数据。
文摘 (Digest.crc32, Digest.adler32, Digest.sha1)
包含数据文件的adler32校验和的文件
CRC(CRC.db)
包含在一个未压缩文件里的块的CRC32的文件。
SSTable索引摘要(SUMMARY.db)
保存在内存中的分区索引的示例。
SSTable表的内容 (TOC.txt)
存储sstable表的内容所有组件列表的文件。
第二索引 (SI_.*.db)
内置第二索引,一个SSTable里可存在多个第二索引。
SSTables是存储在磁盘上的文件。SSTable文件的命名规则在Cassandra2.2和后来的版本中发生了改变,为了缩短文件路径。数据文件存储的位置随着安装方式的不同而不同。对于每一个键空间,数据目录内的目录存储每一个表。例如,/data/data/ks1/cf1-5be396077b811e3a3ab9dc4b9ac088d/la-1-big-Data.db代表一个数据文件。开始表示键空间的名称,以区分流空间或者批量加载数据。这个例子中的十六进制字符串5be396077b811e3a3ab9dc4b9ac088d,追加到表名称后面,来表示唯一的表ID。
Cassandra为每一个表创建一个子目录,这样你可以使用一个表来选择物理驱动器或数据量。这样就提供了把表转移到更快的媒介上的能力来获得更好的性能,比如SSD,而且在存储层上在所有附加的存储设备上划分表以获得更好的I/O平衡。
数据是如何保持的?
Cassandra processes dataat several stages on the write path. Compaction to maintain healthy SSTables isthe last step in the write path process.
Cassandra写过程把数据存储到一个叫做SSTables的结构里。SSTables是不可变的。Cassandra为新插入的或者更新的数据写入一个新时间戳的版本到新的SSTables里,而不是使用插入或者更新的数据去覆盖已存在的行。同样,Cassandra也不删除空间:代替的是,Cassandra把需要删除的数据标记为tombstone(墓碑)。
随着时间的推移,Cassandra可能为每一行写了很多的版本,每一个都在不同的SSTable里。每一个版本都有一个不同的时间戳作为唯一的标志存储。这意味着Cassandra必须有越来越多的SSTables来检索数据的一整排。
为了保持数据库的健壮性,Cassandra周期性的合并SSTables和丢弃旧的数据。这个过程叫做compaction。
Compaction
Compaction通过分区键来合并每一个SSTable里的数据,使用最近的时间戳来选择数据的版本。合并的过程是永久的。因为每一个SSTable里的行是通过分区键排序的,因此合并过程并不使用随机I/O。在移除已删除的列和行以后,compaction过程把SSTables合并到一个单一的SSTables里。旧的SSTables文件只要等待使用文件完成读取以后就会被删除。

Compaction会导致一个临时的磁盘占用和磁盘I/O,这是旧的和新的SSTables同时存在。当它完成以后,compaction释放旧的SSTables占用的磁盘空间。它通过压缩过的SSTables替换旧SSTables来提高了读性能。Cassandra甚至可以在完成写之前直接从新的SSTable里读取数据,而不是等待整个compaction过程完成以后。
当Cassandra处理读和写的时候,它在页缓存里使用新SSTables替换掉旧的SSTables。缓存新的SSTables,把读操作导向新的SSTables是一个渐进的过程-它不会导致戏剧性的缓存丢失。Cassandra提供了可预见的高性能,即使在高负载下。
Compaction策略
Cassandra支持不同的compaction策略。每一个都有自己的优势。理解每一种策略是如果工作的,对于选择适合你自己应用程序工作负载的策略是至关重要的。虽然下面的每一种选择都是以广义的建议开始的,但是有很多复杂的因素影响了compaction策略的选择。有关更多关于每一种策略相对的优势,和指定使用用例的讨论的更多信息,参考:哪一种compaction策略是最好的?
SizeTieredCompactionStrategy(STCS)
推荐用于写密集工作负载
当一组(默认4)相似大小的SSTables累积起来的时候,SizeTieredCompactionStrategy(STCS)初始化compaction。该compaction策略合并这些SSTables成一个更大的SSTable。然后这个更大的SSTables依次合并成一个更大的SSTables。在任何给定的时间里,几个大小不等的SSTables同时存在。

当这个策略在一个写密集的工作负载下运行的很好的时候,它使读变得更慢,因为按大小合并的过程并不倾向于按行分组数据。因为这个原因,它更可能是一个特殊行的数据可能分布在很多的SSTables里。同样,移除已被删除的数据的发生是不可预知的,因为SSTable的大小是compaction过程的触发器,而且SSTables增长的速度可能还不能达到合并和移除旧数据的条件。由于最大的SSTables大小会增长,磁盘compaction空间数量需要同时既容纳新的,也要容纳旧的SSTables,可能超过一个典型的节点的磁盘空间大小。
? Pros:压缩写密集工作负载很不错
? Cons:可以保持过时的数据太长。需要的内存量随着时间的推移而增加。