Golang SortedSet Implementation (Redis skiplist based)

Source: Internet
Author: User

In-game leaderboard is a very common requirement, previously used by Redis SortedSet, just see a LUA implementation, and then ported to the Golang version, GitHub address: Https://github.com/Skycrab/go-zset , the CLI commands for using the method and Redis are basically consistent.

Using the CGO package, the implementation of the skiplist is basically the same as Redis, although CGO is very convenient to use, but it involves a callback to go in C.

It doesn't feel like Lua is refreshing.

Go-zet does not provide a way to persist, and I provide persistence in Https://github.com/Skycrab/cham/blob/master/lib/zset/zset.go . There is primarily no good persistence scheme, unlike the RDB format used by Redis. In Cham, like Redis, the fork writes the file,

It's just that I'm using the JSON format.

Use fork snapshot to Savefunc (z *zset) bgstore (name string) error {F, err: = Helper. LockFile (name, true) if err! = Nil {return err}pid, errno: = helper. Fork () if errno! = 0 {return errors. New ("fork error," + errno. Error ())}//childif pid = = 0 {buf: = Bufio. Newwriter (f) Encoder: = json. Newencoder (BUF) encoder. Encode (Z.TBL) buf. Flush () f.close () OS. Exit (0)}return Nil}

The helper code is as follows:

Package Helperimport ("OS" "Runtime" "Syscall") func Fork () (int, syscall. Errno) {r1, r2, err: = Syscall. Rawsyscall (Syscall. Sys_fork, 0, 0, 0) if Err! = 0 {return 0, err}if runtime. GOOS = = "Darwin" && r2 = = 1 {r1 = 1}return int (r1), 0}//referer http://ikarishinjieva.github.io/blog/blog/2014/03 /20/go-file-lock/func LockFile (name string, truncate BOOL) (*os. File, error) {flag: = OS. O_rdwr | Os. O_createif truncate {flag |= OS. O_trunc}f, err: = OS. OpenFile (name, flag, 0666) if err! = Nil {return nil, err}if err: = Syscall. Flock (int (F.FD ()), Syscall. Lock_ex|syscall. LOCK_NB); Err! = Nil {f.close () return nil, Err}return F, nil}

Let's see if test basically knows how to use it.

Package Zsetimport ("FMT" "Testing" "time") func equal (a []string, b []string) bool {if Len (a)! = Len (b) {return false}for I : = 0; I < Len (a); i++ {if a[i]! = B[i] {return False}}return True}func assert (t *testing. T, OK bool, s string) {if!ok {t.error (s)}}func testbase (t *testing. T) {z: = New () assert (T, z.count () = = 0, "Empty Count Error") Z.add (1, "") Z.add (1, "+") assert (T, z.count () = = 2, "not EMP Ty Count error ") VAR score float64var ex Boolscore, ex = Z.score (" a ") assert (t, score = = 1," score Error ") Z.add (2," a ") ERT (T, z.count () = = 2, "After add duplicate Count error") score, ex = Z.score ("a") assert (t, score = 2, "After add score E Rror ") Z.rem (" a ") assert (T, z.count () = = 1," After Rem Count error ") score, ex = Z.score (" a ") assert (t, ex = = False," not ex IST score Error ") FMT. Println ("")}func Testrangebyscore (t *testing. T) {z: = New () z.add (2, "a") Z.add (1, "one") Z.add (3, "") s: = "Testrangebyscore error" assert (T, equal (Z.rangebyscore (2, 3) , []string{"," + "}), s) assert (T, equal (Z.rangebyscore (0, 5), []string{"one", "Max", "Max"}), s) assert (T, equal (Z.rangebyscore (5), []string{}), s) assert (T, Equal (Z.rangebyscore (0), []string{"", "" "," one "}), s)}func testrange (t *testing.  T) {z: = New () z.add (100.1, "1") Z.add (100.9, "9") Z.add (100.5, "5") assert (T, equal (Z.range (1, 3), []string{"1", "5", "9"}),  "Range1 error") assert (T, equal (Z.range (3, 1), []string{"9", "5", "1"}), "Range2 error") assert (T, equal (Z.revrange (1, 2), []string{"9", "5"}), "RevRange1 error") assert (T, equal (Z.revrange (3, 2), []string{"1", "5"}), "RevRange2 error")}func Te Strank (t *testing. T) {z: = New () assert (T, Z.rank ("kehan") = = 0, "Rank empty Error") Z.add (1111.1111, "Kehan") assert (T, Z.rank ("kehan") = = 1, "Rank error") Z.add (222.2222, "Lwy") assert (T, Z.rank ("kehan") = = 2, "Rank 2 Error") assert (T, Z.revrank ("kehan") = = 1, "REVR Ank error ")}func Testlimit (t *testing. T) {z: = New () z.add (1, "1") Z.add (2, "2") Z.add (3, "3") Z.limit (1) assert (T, z.count () = = 1, "Limit error") assert (T, Z.rank ("3 ") = = 0," LImit Rank Error ") Z.add (4.4," 4 ") Z.add (5.5," 5 ") Z.add (0.5," 0.5 ") Z.dump () assert (T, z.revlimit (4) = = 0," Revlimit error ") ASSERT (T, z.revlimit (0) = = 4, "RevLimit2 error")}func Teststore (t *testing. T) {z: = New () z.add (1, "1") Z.add (2, "2") Z.add (3, "3") Z.bgstore ("Zdb.json") go func () {time. Sleep (time. Second * 2) FMT. Println ("continue add") Z.add (4, "4") Z.add (5, "5")} ()}func Testrestore (t *testing. T) {z: = New () assert (T, len (z.tbl) = = 0, "restore Error") Z.restore ("Zdb.json") fmt. Println (Z.TBL) assert (T, Len (Z.TBL)! = 0, "Restore2 error") assert (T, z.count () = = Len (z.tbl), "Restore3 Error")}




Golang SortedSet Implementation (Redis skiplist based)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.