需求
以前的实现方式
1、DB LIKE .它适用于低并发和少量数据。2、弹性搜索。它适用于高并发和大数据量。
concurrent-trees的介绍
https://github.com/npgall/concurrent-trees Github自动完成是通过同时树的半径和后缀树的特征来实现的,它们可以精确匹配前缀、后缀和模糊。
适用于高并发、小数据量、友好的硬件内存环境。
特点:无锁读取,同一读取线程必须读取相同版本的树。读线程不会阻塞写线程。编写器线程相互阻塞,但读取器线程不会。
实现:编写主要通过打补丁和替换来实现。
在原始树中插入“吐司”来构建补丁(蓝色)。构建时,阅读器线程不受影响,阅读器线程可以读取旧版本(黑色)或新版本(蓝色)。
当读取旧版本的线程完成时,“te”节点可以被回收,最终形成图3的树。
代码示例
精确,前缀匹配使用RadixTree。RadixTreeString radixTree=new concurrentsufixtreestring(new defaultcharsequencenodefinet());
//与键值完全匹配
radix tree . getvalueforactkey(' key ');
//前缀与键值匹配
radix tree . getvalues workysstarting with(' key ');
//前缀与键和值匹配
radix tree . getkeyvaluepairsworkysstarting with(' key ');
//自动完成一般使用RadixTree。
模糊和后缀匹配使用后缀树。
sufixtreestring symbolSuffixTree=new concurrentsufixtreestring(new defaultcharsequencenodeffactory());
//模糊匹配键值
symbolsuffixtree . getvalues workyscontaining(' key ');
//后缀与键值匹配
symbolsuffixtree . getvaluesforkeysendingwith(' key ');更多信息请参考官方文件。
00-1010 1.注意记忆。尤其是后缀树。推荐使用
属国
groupIdorg.apache.lucene/groupId
artifactIdlucene-核心/artifactId
版本4 . 0 . 0/版本
/dependencyramusage estimator . humansizeof(后缀树);检查内存使用情况。
2.这棵树不适合萝卜。比如在我们的实际使用中,后缀树都是m,每个请求都必须从Radis本地取,对内存和网络影响很大,应该放在本地内存中。
但这导致了另一个问题。如果我们的程序是分布式部署,当Tree需要更新时,被调用的提供者接口通常是N (Dubbo,Spring Cloud)中的一个,只会更新其中一个树。
解决方案是利用Dubbo的广播集群、Spring Cloud Bus、Elastic-Job切片机制,保证逐个调用提供者的更新Tree接口,更新所有切片内存中的树。
当然,对于一定的碎片故障,需要制定容错机制。
3.更新树时,除了将数据源的新数据放入树中,我们还应该考虑删除不在数据源中但在树中的数据。
4.密钥区分大小写。